前言
本文主要從UINavigationController,UINavigationBar和UINavigationItem的概念入手钳吟,通過介紹這三者之間的關(guān)系,來學(xué)會(huì)導(dǎo)航控制器的使用贴见。
學(xué)習(xí)新知識分為兩個(gè)狀態(tài):學(xué)會(huì)如何運(yùn)用和理解知識的原理烘苹,自如運(yùn)用。本篇主要側(cè)重于后者片部。
self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationItem.title = @"我是標(biāo)題";
通常镣衡,我們都是這樣設(shè)置導(dǎo)航欄的樣式。但是為什么標(biāo)題需要使用視圖控制器的navigationItem對象中設(shè)置,而導(dǎo)航欄的背景色卻是在導(dǎo)航控制器navigationBar對象中設(shè)置廊鸥?
接下來我們看一下蘋果文檔中對三者的解釋:
一望浩、UINavigationController
UINavigationController是一種可以管理層級內(nèi)容的導(dǎo)航控制器,也就是我們常說的容器控制器惰说。它通過一個(gè)棧對象實(shí)現(xiàn)了不同ViewController之間的跳轉(zhuǎn)和返回操作磨德。棧底的viewcontroller稱為rootViewController, 棧頂?shù)膶ο缶褪钱?dāng)前顯示在屏幕上的ViewController.
官方文檔
A navigation controller object manages the currently displayed screens using the navigation stack, which is represented by an array of view controllers. The first view controller in the array is the root view controller. The last view controller in the array is the view controller currently being displayed. You add and remove view controllers from the stack using segues or using the methods of this class. The user can also remove the topmost view controller using the back button in the navigation bar or using a left-edge swipe gesture.
二、UINavigationBar
UINavigationBar是顯示在屏幕最上方的一條bar吆视,包含了當(dāng)前view上的一些導(dǎo)航按鈕典挑,主要有左側(cè)的返回按鈕,居中的標(biāo)題欄和可選的右側(cè)按鈕啦吧∧酰可以單獨(dú)使用也可以和UINavigationController結(jié)合在一起使用。
UINavigationController負(fù)責(zé)控制顯示在界面頂部的UINavigationBar和一個(gè)可選的顯示在界面底部的toolbar丰滑。UINavigationBar默認(rèn)顯示顾犹,UINavigationController負(fù)責(zé)在頁面跳轉(zhuǎn)時(shí)使用當(dāng)前棧頂viewController的內(nèi)容更新UINavigationBar.
官方文檔
A UINavigationBar object is a bar, typically displayed at the top of the window, containing buttons for navigating within a hierarchy of screens. The primary components are a left (back) button, a center title, and an optional right button. You can use a navigation bar as a standalone object or in conjunction with a navigation controller object.
The navigation controller manages the navigation bar at the top of the interface and an optional toolbar at the bottom of the interface. The navigation bar is always present and is managed by the navigation controller itself, which updates the navigation bar using the content provided by the view controllers on the navigation stack.
三倒庵、UINavigationItem
UINavigationItem對象負(fù)責(zé)管理顯示在UINavigationBar中的按鈕和視圖褒墨。當(dāng)創(chuàng)建一個(gè)UINavigationController界面時(shí),每一個(gè)進(jìn)棧的viewController都必須有一個(gè)UINavigationItem對象擎宝;UINavigationItem對象中包含了要顯示在導(dǎo)航欄上的按鈕或者視圖郁妈。導(dǎo)航控制器使用最上層的兩個(gè)viewcontroller中的navigationItem中的內(nèi)容來展示當(dāng)前的導(dǎo)航欄。
官方文檔
A UINavigationItem object manages the buttons and views to be displayed in a UINavigationBar object. When building a navigation interface, each view controller pushed onto the navigation stack must have a UINavigationItem object that contains the buttons and views it wants displayed in the navigation bar. The managing UINavigationController object uses the navigation items of the topmost two view controllers to populate the navigation bar with content.
蘋果的UINavigationBar官方文檔中有一段對三者的關(guān)系的描述非常關(guān)鍵:
當(dāng)視圖控制器在導(dǎo)航過程中绍申,導(dǎo)航控制利用視圖控制器提供的navigationItem的屬性作為導(dǎo)航控制器的導(dǎo)航欄的model對象噩咪。navigationItem默認(rèn)使用視圖控制器的title屬性,但是我們也可以通過自定義navigationItem的屬性達(dá)到完全控制導(dǎo)航欄內(nèi)容的效果。
A navigation controller uses the navigationItem property on UIViewController to provide the model objects to its navigation bar when navigating a stack of view controllers. The default navigation item uses the view controller’s title, but you can override the navigationItem on a UIViewController subclass to gain complete control of the navigation bar’s content.
四、三者的關(guān)系:
- 每一個(gè)導(dǎo)航控制器都會(huì)自動(dòng)生成一個(gè)與之對應(yīng)的導(dǎo)航欄(UINavigationBar)對象瓶珊;
- 當(dāng)一個(gè)新的ViewController加入到導(dǎo)航控制器時(shí)管削,導(dǎo)航欄使用ViewController提供的navigationItem對象作為導(dǎo)航欄的model對象來渲染導(dǎo)航欄;
- 導(dǎo)航欄會(huì)保存導(dǎo)航控制器棧內(nèi)最上層的兩個(gè)ViewController的navigationItem對象;
- ViewController從導(dǎo)航控制器棧移除時(shí)慌闭,navigationItem會(huì)同時(shí)從navigationBar的視圖棧內(nèi)移除。
五、實(shí)踐
理清楚三者之間的關(guān)系后, 實(shí)現(xiàn)一個(gè)指定效果的導(dǎo)航欄就變得非常簡單:
- 生成導(dǎo)航控制器俄周,并指定rootViewController;
ViewController *viewController = [[ViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navigationController;
- 通過navigationBar設(shè)置導(dǎo)航欄的外觀,包括顏色和tintColor;
self.navigationController.navigationBar.backgroundColor = [UIColor orangeColor];
self.navigationController.navigationBar.tintColor = [UIColor grayColor];
- 新建一個(gè)ViewController,通過設(shè)置其navigationItem來實(shí)現(xiàn)指定的效果髓迎;
self.navigationItem.title = @"首頁";
P.S. 總之峦朗,如果需要改變navigationBar的外觀,就在navigationBar對象上做文章排龄,如果需要在導(dǎo)航欄上顯示按鈕或者視圖波势,就在navigationItem屬性上做文章。
六、深入驗(yàn)證理論(不感興趣的可以跳過不看)
這個(gè)部分主要通過調(diào)試手段驗(yàn)證第四部分的理論尺铣,有興趣的可以動(dòng)手驗(yàn)證一下闭翩,對您的學(xué)習(xí)大有裨益。
在你的項(xiàng)目中迄埃,準(zhǔn)備三個(gè)ViewController, 分別設(shè)置其導(dǎo)航欄標(biāo)題和背景色疗韵,跳轉(zhuǎn)順序?yàn)锳 -> B -> C,并分別在三個(gè)頁面的viewDidAppear代理方法中打上斷點(diǎn)侄非,運(yùn)行程序蕉汪。
驗(yàn)證一:程序停留在A頁面,使用lldb打印navigationBar對象
po self.navigationController.navigationBar //UINavigationBar: 0x7f8b1b508e50;
繼續(xù)執(zhí)行逞怨,并點(diǎn)擊按鈕者疤,從A頁面跳轉(zhuǎn)到B頁面,程序會(huì)停留在B頁面叠赦,同樣打印navigationBar
po self.navigationController.navigationBar //UINavigationBar: 0x7f8b1b508e50;
由此可見驹马,無論在哪個(gè)頁面,使用的都是同一個(gè)navigationBar對象除秀;
驗(yàn)證二糯累、有視圖控制器進(jìn)棧時(shí),導(dǎo)航欄使用視圖控制器的navigationItem對象作為model對象册踩。
保留斷點(diǎn)泳姐,重新運(yùn)行項(xiàng)目,讓斷點(diǎn)停留在A頁面暂吉,使用lldb打印navigationItem和navigationBar
po self.navigationItem //<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'>
po self.navigationController.navigationBar.subviews
//
//<__NSArrayM 0x600000055870>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1b614930; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000234200>>: item=<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'> title=頁面A>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
//)
//
由此可知胖秒,當(dāng)新的ViewController入棧時(shí),navigationBar會(huì)使用ViewController提供的navigationItem對象慕的。
驗(yàn)證三阎肝、navigationBar只保留最上層的2個(gè)viewController的navigationItem.
在頁面B和C分別打印navigaitonBar, 得到的結(jié)果如下:
po self.navigationController.navigationBar.subviews
//__NSArrayM 0x608000053da0>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1d00f9d0; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000234200>>: item=<<UINavigationItem: 0x6000001c8e80>: title:'頁面B'> title=頁面B>,
//<<UINavigationItemButtonView: 0x7f8b1b614930; frame = (8 6; 54 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000036520>>: item=<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'> title=頁面A>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
)
po self.navigationController.navigationBar.subviews
//<__NSArrayM 0x618000053fe0>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1d00fdc0; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000236120>>: item=<<UINavigationItem: 0x6000001c9240>: title:'頁面C'> title=頁面C>,
//<<UINavigationItemButtonView: 0x7f8b1b617410; frame = (8 6; 106 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000373a0>>: item=<<UINavigationItem: 0x6000001c8e80>: title:'頁面B'> title=頁面B>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
)
由此可見,navigationBar確實(shí)只保存了最上層的2個(gè)viewController的navigationItem.
驗(yàn)證四肮街、ViewController從導(dǎo)航控制器移除后风题,navigationItem也會(huì)從navigationBar中被移除。
這個(gè)大家自行驗(yàn)證一下低散。
能堅(jiān)持讀到這里的同學(xué)俯邓,都非常有耐心的??
七、練習(xí)部分
既然已經(jīng)花費(fèi)了這么多精力熔号,那就趁熱打鐵稽鞭,練習(xí)一下。
- 實(shí)現(xiàn)微信我的-朋友圈頁面的導(dǎo)航效果引镊;