導航控制器
- 導航控制器基礎
- 基本概念
- 具體使用
- 導航控制器切換
- 演示
- 具體使用
- 注意
- 導航欄與工具欄
- 基本概念
- 具體使用:
- 總結
導航控制器基礎
基本概念
- 根視圖控制器(Root View Controller):導航控制器的第一個視圖控制器,通常是應用程序的主屏幕。
- 導航欄(Navigation Bar):用于顯示當前視圖控制器的標題以及在導航棧中的位置。
- 工具欄(Toolbar):可選的,用于顯示當前視圖控制器的工具按鈕。
- 返回按鈕(BackButton):用于在導航欄中返回上一個視圖控制器。
下圖是一個導航欄的組成。
具體使用
首先我們要創建一個根視圖控制器,該類繼承UIViewController。
然后我們在SceneDelegate.m中我們創建一個根視圖控制器對象和導航控制器對象。
#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {self.window.frame = [UIScreen mainScreen].bounds;//創建一個根視圖控制器VCRoot *root = [[VCRoot alloc] init];//創建導航控制器//導航控制器主要用來管理多個視圖控制器的切換//層級的方式來管理多個視圖控制器//創建控制器時,一定要有一個根視圖控制器UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: root];root.view.backgroundColor = [UIColor blueColor];//將windows的根視圖設置為導航控制器self.window.rootViewController = nav;[self.window makeKeyAndVisible];
}
隨后,我們在我們創建的根視圖控制器的實現接口中,完成對導航欄屬性的學習。
- UIBarButtonItem:是 iOS 中用于創建和管理導航欄、工具欄等界面元素的類。
該類有三種初始化方法,一個是自定義文本,一個是使用系統風格,一個是將其他類型的控件作為按鈕。 self.title = @"根視圖"與 self.navigationItem.title = @"Title";
:這兩個都是設置導航欄標題的屬性,navigationItem.title的優先級高于title
#import "VCRoot.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor yellowColor];//設置導航欄的標題文字self.title = @"根視圖";//上下都是設置title//如果沒有設置navigationItem.title,為nil,//系統則會使用self。title作為標題。//優先下,再看上,如無下,則將上賦值給下//設置導航元素項目的標題self.navigationItem.title = @"Title";//創建一個導航欄左側的按鈕//根據title文字來創建按鈕//P1:按鈕上的文字//P2:按鈕風格//P3:事件擁有者//P4:按鈕事件//Bar專門用在導航欄上的按鈕UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithTitle:@"左側" style:UIBarButtonItemStyleDone target:self action:@selector(pressLeft)];//導航元素項的左側按鈕賦值self.navigationItem.leftBarButtonItem = leftBtn;//創建一個導航欄左側的按鈕//根據系統風格創建按鈕//P1:按鈕上的文字//P2:按鈕風格//P3:事件擁有者//只需要指定風格樣式,系統風格的按鈕內容或標題文字不能改變UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(pressRight)];UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 50, 40)] ;label.text = @"test";label.textAlignment = NSTextAlignmentCenter;//將任何類型的控件添加到導航按鈕的方法UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:label] ;//添加多個按鈕,創建按鈕數組NSArray *arrayBtn = [NSArray arrayWithObjects:rightBtn,item3, nil ];UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(press:)];[label addGestureRecognizer:tap];label.userInteractionEnabled = YES;self.navigationItem.rightBarButtonItems = arrayBtn;
}-(void)press: (UITapGestureRecognizer*)tap {NSLog(@"press");
}
-(void) pressLeft
{NSLog(@"左側按鈕被按下!");
}-(void) pressRight
{NSLog(@"右側按鈕被按下!");
}@end
效果:
導航控制器切換
演示
下圖為通過點擊切換了不同的視圖,而我們通過導航控制器也可以實現這一需求。
具體使用
首先我們創建三個視圖控制器。
然后,與上面所學相同,我們需要在SceneDelegate.m中我們創建一個根視圖控制器對象和導航控制器對象。
#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {self.window.frame = [UIScreen mainScreen].bounds;VCRoot *root = [[VCRoot alloc] init];UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root];self.window.rootViewController = nav;[self.window makeKeyAndVisible];}
接著,我們在根視圖中使用導航欄進行下一級視圖控制器的推出。
首先學習translucent
屬性,該屬性用于控制視圖控制器是否透明,默認為YES,透明的。
不透明效果:
我們通過創建一個按鈕,在響應事件中添加pushViewController: animated:
方法,來實現下一個視圖的推出。注意,需要新建下一級視圖控制器
#import "VCRoot.h"
#import "VCSecond.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];//設置導航欄的透明度//默認透明度為YES,可透明的。//NO為不透明。self.navigationController.navigationBar.translucent = YES;self.navigationController.navigationBar.barStyle = UIBarStyleDefault;self.view.backgroundColor = [UIColor whiteColor];self.title = @"根視圖";UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"下一級" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];self.navigationItem.rightBarButtonItem = next;
}-(void) pressNext
{//創建新的視圖控制器VCSecond* vcSecond = [[VCSecond alloc] init];//使用當前視圖控制器的導航控制器對象,推出vcSecond控制器//參二為是否需要添加動畫效果[self.navigationController pushViewController:vcSecond animated:YES];
}@end
同樣的,我們在二級視圖中用相同的方法推出第三級視圖
#import "VCSecond.h"
#import "VCThired.h"
@interface VCSecond ()@end@implementation VCSecond- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor greenColor];self.title = @"兒子視圖";UIBarButtonItem *btnNext = [[UIBarButtonItem alloc] initWithTitle:@"第三級" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];self.navigationItem.rightBarButtonItem = btnNext;
}-(void) pressNext
{VCThired *vc = [[VCThired alloc] init];[self.navigationController pushViewController:vc animated:YES];
}
我們在第三級中,自己設定左側按鈕,此時會發現自己設定的按鈕樣式會覆蓋系統的按鈕樣式。
當迭代到第三級后,我們想直接返回到根視圖時,可以使用popToRootViewControllerAnimated
方法作為響應事件,直接返回到根視圖。
#import "VCThired.h"@interface VCThired ()@end@implementation VCThired- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.title = @"孫子視圖";UIBarButtonItem *btnLeft = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(pressBack)];UIBarButtonItem *btnRight = [[UIBarButtonItem alloc] initWithTitle:@"返回根視圖" style:UIBarButtonItemStylePlain target:self action:@selector(pressRight)];//當自己設定左側按鈕時//返回按鈕會被左側按鈕替換self.navigationItem.leftBarButtonItem = btnLeft;self.view.backgroundColor = [UIColor blueColor];self.navigationItem.rightBarButtonItem = btnRight;
}-(void) pressRight
{[self.navigationController popToRootViewControllerAnimated:YES];
}-(void) pressBack
{//將當前的視圖控制器彈出,返回上一級界面[self.navigationController popViewControllerAnimated:YES];
}@end
效果展示:
注意
在每一個視圖中,我們進行視圖的推出和返回時,都對self.navigationController
對象進行。那這個self.navigationController對象是不同的三個對象呢,還是同一個對象?
實際上,三個不同視圖中的self.navigationController對象都是同一個對象。
這與導航控制器推出視圖控制器的方式有關:通過 [self.navigationController pushViewController:vc animated:YES]
方法將視圖控制器 vc 推入導航堆棧時,vc 成為導航堆棧的最頂層視圖控制器,但導航控制器對象本身并沒有改變。
因此:我們每次看到的視圖就是導航堆棧的棧頂,使用push是將視圖控制器推入棧頂,使用pop是將視圖控制器推出棧頂。
而因為導航控制器對象本身是沒有改變的,所以我們設置了根視圖的導航控制器,就設置了所有視圖的導航控制器
導航欄與工具欄
基本概念
導航欄前面已經介紹了,我們在此著重介紹工具欄。
工具欄的組件:
- 固定空間按鈕(Fixed Space Bar Button):固定空間按鈕是另一種特殊類型的工具欄按鈕,用于創建固定寬度的間距。它可以用于調整按鈕之間的間距或在工具欄上創建對齊效果。
- 標簽(Label):用于顯示相關的信息或標題,提供上下文或描述工具欄中的操作。
- 圖片視圖(Image View):用于顯示圖標、圖像或其他視覺元素。圖像視圖可以代表特定的操作或提供視覺上的識別。
- 自定義視圖(Custom View):自定義的視圖元素,自定義視圖可以是任何 UIView 的子類,允許你在工具欄上添加自定義的界面元素,如文本輸入框、開關按鈕等。
工具欄的基本元素:
- 工具欄按鈕(Toolbar Button):工具欄中的單個按鈕,可以通過點擊來執行特定操作或導航到其他屏幕。
- 工具欄項(ToolbarItem):工具欄中的一個單獨元素,可以包含一個或多個工具欄按鈕。
- 工具欄控制器(ToolbarController):用于管理工具欄的視圖控制器,可以使用工具欄控制器來添加、刪除和重新排列工具欄項。
- 工具欄樣式(ToolbarStyle):工具欄的外觀樣式,可以通過設置工具欄的顏色、透明度、背景圖像和按鈕樣式等屬性來自定義工具欄的外觀。
具體使用:
導航欄的創建在此不再贅述,我們直接進入學習
隱藏導航欄的兩個方法:
//該屬性默認為NOself.navigationController.navigationBar.hidden = NO;self.navigationController.navigationBarHidden = NO;
在iOS13之后,我們使用UIBarAppearance類設置導航控制器的外觀樣式
//UIBarAppearance是iOS13后推出的一個對相應空間設置外觀樣式的類,可以統一配置NavigationBar、TabBar、ToolBar等的外觀樣式//UINavigationBarAppearance可以設置導航欄對象的外觀樣式//創建一個UINavigationBarAppearance對象UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];//背景顏色appearance.backgroundColor = [UIColor whiteColor];//陰影appearance.shadowImage = [[UIImage alloc] init];appearance.shadowColor = nil;self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
接著,我們將默認為隱藏的工具欄開啟,并且設置三個不同的按鈕來演示工具欄按鈕的使用。
此處與導航控制器一樣,我們分別采用三種初始化方法,來實現文本,系統風格,和自定義圖像的初始化。
與導航控制器不同的是,此處我們額外使用固定空間按鈕或者彈簧按鈕,實現將工具欄的按鈕以相同間距排列。
//顯示工具欄對象//默認工具欄是隱藏的self.navigationController.toolbarHidden = NO;self.navigationController.toolbar.translucent = NO;//創建三個工具欄按鈕UIBarButtonItem *btn1 = [[UIBarButtonItem alloc] initWithTitle:@"left" style:UIBarButtonItemStylePlain target:nil action:nil];UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(pressNext)];UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom];[btnImage setImage:[UIImage imageNamed:@"7_.jpg"] forState:UIControlStateNormal];btnImage.frame = CGRectMake(0, 0, 60, 60);UIBarButtonItem *btn3 = [[UIBarButtonItem alloc] initWithCustomView:btnImage];//位置分開//法一:固定控件按鈕
// UIBarButtonItem *btnF1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
//
// btnF1.width = 100;//法二://創建自動計算按鈕,彈簧按鈕UIBarButtonItem *btnF2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];//按鈕數組的創建NSArray *arrayBtns = [NSArray arrayWithObjects:btn1, btnF2, btn2, btnF2, btn3, nil];self.toolbarItems = arrayBtns;}- (void) pressNext
{ //使用此按鈕彈出下一視圖。VCSecend *vc = [[VCSecend alloc] init];[self.navigationController pushViewController:vc animated:YES];}- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:NO animated:animated];
}
效果:
點擊照相機后:
在上面的效果中,當進入第二個視圖我們的工具欄消失了,使用如下代碼實現:
在根視圖中加入:
- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:NO animated:animated];
}
在二視圖中加入:
- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:YES animated:animated];
}
即可實現。
總結
導航控制器是UI學習的重要一部分,經過這篇總結融會貫通,我覺得我又行咯。