好久沒有更新了铜靶,近日把項(xiàng)目中遇到的NavigationController 相關(guān)技術(shù)點(diǎn)梳理一下倍权,與大家共同分享
首先來點(diǎn)基礎(chǔ)的屬性
一. 基本屬性
設(shè)置顏色
如果項(xiàng)目中 Navigation 都是統(tǒng)一的抽高,而你又懶得單獨(dú)抽取一個BaseNavigationController汰寓,可以直接在 [appDelegate didFinishLaunchingWithOptions]方法中寫
//設(shè)置NavigationBar背景顏色
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
// 通過富文本設(shè)置title 樣式(這里也可以通過自定義Label芍锦,然后設(shè)置 titleView 來實(shí)現(xiàn))
[[UINavigationBar appearance] setTitleTextAttributes:@{
NSForegroundColorAttributeName : [UIColor whiteColor]
}];
// 設(shè)置狀態(tài)欄格式斤儿,如果 NavigationBar 為深色調(diào)励饵,就設(shè)置為 UIBarStyleBlack驳癌,則狀態(tài)欄顯示為白色
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
實(shí)現(xiàn) NavigationBar 透明效果
實(shí)現(xiàn)透明可能大家第一個想到的是 設(shè)置 alpha 值,但是由于設(shè)置了作為父控件的 NavigationBar 的透明度后役听,其子控件 BarButtonItem 也會隨之改變颓鲜,因此想要實(shí)現(xiàn)導(dǎo)航欄透明,但是 BarButtonItem 正常顯示(類似 手機(jī)QQ 的好友動態(tài)頁)典予,可以采用下面的方法
// 設(shè)置一個空的圖片背景圖片甜滨,就能實(shí)現(xiàn)導(dǎo)航欄透明但是 BarButtonItem 正常顯示
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
然而設(shè)置之后乍一看沒問題,可仔細(xì)一看你會發(fā)現(xiàn)NavigationBar下面還有一條細(xì)線熙参,這個細(xì)線就是shadow
快看那條淡淡的細(xì)線艳吠!
層級關(guān)系圖
可通過以下代碼來去掉
// 設(shè)置一個空的 shadowImage 來實(shí)現(xiàn)
self.navigationController.navigationBar.shadowImage = [UIImage new];
那么有同學(xué)可能要問了,一直透明的可以通過上述方法來實(shí)現(xiàn)孽椰,那如果想要隨著 上拉距離的改變昭娩,實(shí)現(xiàn)其透明度動態(tài)變化要怎么做?
// 這個就要監(jiān)聽 scrollView 的 offset
// 然后獲取到 NavigationBar復(fù)合視圖 的顯示子控件黍匾,動態(tài)改變其透明度
[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = 0;
既然講到這里了就說下來回 push 或 pop栏渺,以及使用手勢來返回的時候,上下層級之間 NavigationBar 隱藏與否的設(shè)置锐涯,因?yàn)槿绻@里沒處理好的話磕诊,會有一個黑條,或者直接顯示下一層級的視圖,體驗(yàn)特別差霎终,這時候就需要通過動畫的方式的在下一層級進(jìn)行設(shè)置
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// 當(dāng)前 VC 需要顯示 navigationBar 就設(shè)置為 NO滞磺,需要隱藏就設(shè)置為 YES
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
側(cè)滑手勢相關(guān)
很多時候,leftBarButtonItem需要自定義莱褒,因?yàn)槟J(rèn)的顯示上一層級的title不一定是我們想要的击困,但是自定義改變之后,會發(fā)現(xiàn)側(cè)滑返回的手勢不好使了
#warning 這時候就需要在當(dāng)前 VC 中設(shè)置手勢代理了
self.interactivePopGestureRecognizer.delegate = self;
// 實(shí)現(xiàn)代理方法:返回 YES广凸,則手勢有效
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
//當(dāng)導(dǎo)航控制器的子控制器個數(shù) 大于1 手勢才有效
return self.childViewControllers.count > 1;
}
由于項(xiàng)目中同一個 VC阅茶,有時候是 modal 出來的,有時候是 push 出來的谅海,那么在這個VC中就要判斷進(jìn)行處理
NSArray *viewcontrollers=self.navigationController.viewControllers;
if (viewcontrollers.count > 1) {
if ([viewcontrollers objectAtIndex:viewcontrollers.count - 1] == self) {
// push方式
[self.navigationController popViewControllerAnimated:YES];
}
} else {
// present方式
[self dismissViewControllerAnimated:YES completion:nil];
}
如果要實(shí)現(xiàn)如下效果的導(dǎo)航欄脸哀,設(shè)置 leftBarButtonItems 和 rightBarButtonItems 即可
喂!焦點(diǎn)在 NavigationBar扭吁,老看 tableView 干啥撞蜂!
關(guān)于 rootVC 的 offset,先來看幾個 ViewController 的屬性
iOS7以后默認(rèn)設(shè)置是 UIRectEdgeAll侥袜,translucent 的默認(rèn)值是 true谅摄,這個組合會使 rootView 的布局從 (0, 0) 開始,就會造成 rootView 被 NavigationBar 遮擋住一部分系馆,將 edgesForExtendedLayout 設(shè)置為 UIRectEdgeNone 即可解決問題
automaticallyAdjustsScrollViewInsets 默認(rèn)值是 YES送漠,表示在全屏下會自動將 第一個添加到 rootVC 的 ScrollView 的 contentInset 設(shè)置為 (64, 0, 0, 0),這樣 scrollView 就不會被導(dǎo)航欄遮擋住了
二. 來回跳轉(zhuǎn)
項(xiàng)目中有個需求是A push 到 B, B push 到 C由蘑, C pop 到 D闽寡,D 再 pop到 A,就好比這樣:
類似這種交叉跳轉(zhuǎn)的感覺
首先 A push 到 B尼酿,直接使用
[self.navigationController pushViewController:B animated:YES];
// 此時 self.navigationController.childViewControllers = [A, B];
然后 B push 到 C爷狈,同理
[self.navigationController pushViewController:C animated:YES];
// 此時 self.navigationController.childViewControllers = [A, B, C];
現(xiàn)在要實(shí)現(xiàn) C pop 到 D,由于 navigationController.childViewControllers 是只讀的裳擎,因此不能直接對其進(jìn)行操作
navigationController.childViewControllers 是只讀的
// 建立可變拷貝對象涎永,然后進(jìn)行替換操作
NSMutableArray *navChildMArr = [self.navigationController.childViewControllers mutableCopy];
[navChildMArr replaceObjectAtIndex:1 withObject:D];
// 當(dāng)然,最后再將替換后的數(shù)組賦值回去不要忘了
[self.navigationController setViewControllers:navChildMArr animated:YES];
#warning 至于寫上面這串代碼的時機(jī):寫在 B push C 之后可以鹿响,寫在 C 的 viewDidLoad() 方法中也可以
最后的效果如圖
對羡微,效果如圖
就四這么簡單!
如果有其他問題惶我,可以在留言處寫下來妈倔,不定期更新
來自:http://www.reibang.com/p/a1a0c053fb12