一、UINavigationBar
1、導(dǎo)航條navigationbar屬于導(dǎo)航控制器,一個(gè)導(dǎo)航控制器只有一個(gè)導(dǎo)航條。
2、在一個(gè)導(dǎo)航控制器push新頁(yè)面和pop頁(yè)面時(shí),導(dǎo)航條是同一個(gè)。
3、在一個(gè)視圖控制器內(nèi)改變了導(dǎo)航條的樣式,其它控制器的導(dǎo)航條的樣式也會(huì)改變,也說(shuō)明了導(dǎo)航條屬于導(dǎo)航控制器,而不是每個(gè)視圖控制器都有一個(gè)導(dǎo)航條。
4、導(dǎo)航條的層級(jí)結(jié)構(gòu)
navigationbar層級(jí):

UIBarBackground視圖是比UINavigationBar視圖要大
主要屬性:
1.只讀屬性Items,backItem,topItem分別表示為數(shù)組,上一個(gè)控制器,當(dāng)前控制器(棧頂控制器)
也就是說(shuō)UINavigationBar維護(hù)著每個(gè)VC的navigationItem
2.translucent
影響VC.view原點(diǎn)坐標(biāo)
一個(gè)controller的view的原點(diǎn)位置受self.navigationController. navigationBar 的 setTranslucent (BOOL) 屬性控制,在 iOS7 以后 translucent 屬性默認(rèn)為 YES。
translucent 為YES:原點(diǎn)位置坐標(biāo)為屏幕左頂端,即屏幕坐標(biāo)系(0 , 0),含義為毛玻璃、半透明效果。
translucent 為NO:原點(diǎn)位置坐標(biāo)為導(dǎo)航欄的下邊的左頂端,即屏幕坐標(biāo)系(0 , 64),此時(shí)導(dǎo)航欄不透明。
注意,當(dāng)我們?cè)O(shè)置navigationBar的背景圖片setBackgroundImage(注意是背景圖片不是背景顏色)的時(shí)候,坐標(biāo)起點(diǎn)也會(huì)變成(0,64),因?yàn)楫?dāng)我們?cè)O(shè)置背景圖片的時(shí)候,系統(tǒng)會(huì)自動(dòng)修改translucent為NO。其實(shí)navController不僅有UINavigationBar屬性還有個(gè)toolbar屬性(默認(rèn)hiddenYES),toolbar的translucent會(huì)影響到VC.view的高度,也就是是否延伸到屏幕底部。
3.tintColor
bar上的文字按鈕顏色
4.barTintColor
bar的背景色 ios15之后設(shè)置無(wú)效
由于ios15新特性(bar的背景默認(rèn)是透明,滾動(dòng)后與關(guān)聯(lián)的scrollview相交才顯示bar的背景),需要通過UINavigationBarAppearance設(shè)置bar的背景,scrollEdgeAppearance控制與視圖不相交時(shí)bar的樣式,默認(rèn)是透明的;standardAppearance控制與視圖相交時(shí)bar的樣式,
if (@available(iOS 15, *)) {
UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc]init];
navBarAppearance.backgroundImage = whiteBG;
navBarAppearance.shadowImage = whiteBG;
navBarAppearance.titleTextAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18]};
//設(shè)置相交狀態(tài)
[UINavigationBar appearance].standardAppearance = navBarAppearance;
//設(shè)置不相交狀態(tài)
[UINavigationBar appearance].scrollEdgeAppearance = navBarAppearance;
}
二、UINavigationItem
UINavigationBar是由UINavigationController管理的,但是它的樣式由子控制器的self. navigationItem來(lái)設(shè)置。
也就是說(shuō)UINavigationBar是全局設(shè)置的一經(jīng)修改,這個(gè)nav內(nèi)的所有導(dǎo)航條都發(fā)生變化,而UINavigationItem是針對(duì)每個(gè)VC的,是VC的只讀屬性
所以我們應(yīng)當(dāng)通過修改UINavigationItem的屬性來(lái)自定義每個(gè)頁(yè)面的導(dǎo)航條標(biāo)題/按鈕等控件
主要屬性:
titleView
leftBarButtonItem,leftBarButtonItems
rightBarButtonItem,rightBarButtonItems
backBarButtonItem
栗子:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"這是返回" style:UIBarButtonItemStylePlain target:self action:@selector(back)];
三、UIBarButtonItem
UINavigationItem的left/right/back的樣式是通過UIBarButtonItem創(chuàng)建,常用初始化方法:
UIBarButtonItem : UIBarItem:NSObject
- (instancetype)initWithImage:(nullable UIImage *)image style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;
- (instancetype)initWithImage:(nullable UIImage *)image landscapeImagePhone:(nullable UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(ios(5.0)); // landscapeImagePhone will be used for the bar button image when the bar has Compact or Condensed bar metrics.
- (instancetype)initWithTitle:(nullable NSString *)title style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;
- (instancetype)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(nullable id)target action:(nullable SEL)action;
- (instancetype)initWithCustomView:(UIView *)customView;
leftBarButtonItem顯示原則:
1.如果當(dāng)前的視圖控制器設(shè)置了leftBarButtonItem,則顯示當(dāng)前VC所自帶的leftBarButtonItem。
2.如果沒有設(shè)置leftBarButtonItem,且不是根視圖控制器的時(shí)候,則顯示前一層的backBarButtonItem。如果前一層沒有指定backBarButtonItem的話,系統(tǒng)將會(huì)根據(jù)前一層的title屬性自動(dòng)生成一個(gè)back按鈕,并顯示出來(lái)。
3.如果沒有設(shè)置leftBarButtonItem,且已是根視圖控制器的時(shí)候,左邊不顯示任何東西。
理解:backBarButtonItem不是顯示在當(dāng)前VC的,而是其他VC返回此VC時(shí)候的返回按鈕,如果其他VC設(shè)置了left,那么left優(yōu)先級(jí)高于此VC的backBarButtonItem,例如:
設(shè)置VC1的backBarButtonItem,從VC1push到VC2,如果VC2沒設(shè)置leftBarButtonItem,那么VC2的左上角返回按鈕就是VC1的backBarButtonItem,否則優(yōu)先左上角顯示VC2的leftBarButtonItem
總結(jié)
navigationcontroller直接控制viewcontrollers集合,然后它包含的navigationbar是整個(gè)工程的導(dǎo)航欄,bar有一個(gè)用來(lái)管理navigationItem的棧。@property(nonatomic, copy) NSArray <UINavigationItem *> *items
理清以上三者的關(guān)系后,可以單獨(dú)用導(dǎo)航欄UINavigationBar,(不是采用UINavigationController)
代碼方式:
- (void)viewDidLoad{
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)];
//添加NavigationBar到視圖上
[self.view addSubview:navBar];
UINavigationItem *navItem = [[UINavigationItem alloc]initWithTitle:@"welcome page"];
UIBarButtonItem *btnlogin = [[UIBarButtonItem alloc]initWithTitle:@"login" style:UIBarButtonItemStyleDone target:self action:@selector(login)];
navItem.leftBarButtonItem = btnlogin;
//把NavigationItem添加到導(dǎo)航欄上(進(jìn)棧)
[navBar pushNavigationItem:navItem animated:NO];
}
navigationcontroller和navigationbar是一對(duì)一的關(guān)系,而navigationbar和navigationItem則是一對(duì)多的關(guān)系。