2016.12.04數組
很久沒有更新博客了,近日把項目中遇到的NavigationController 相關技術點梳理一下,與你們共同分享app
//設置NavigationBar背景顏色
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
// 經過富文本設置title 樣式(這裏也能夠經過自定義Label,而後設置 titleView 來實現)
[[UINavigationBar appearance] setTitleTextAttributes:@{
NSForegroundColorAttributeName : [UIColor whiteColor]
}];
// 設置狀態欄格式,若是 NavigationBar 爲深色調,就設置爲 UIBarStyleBlack,則狀態欄顯示爲白色
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
複製代碼
// 設置一個空的圖片背景圖片,就能實現導航欄透明可是 BarButtonItem 正常顯示
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
複製代碼
然而設置以後乍一看沒問題,可仔細一看你會發現NavigationBar下面還有一條細線,這個細線就是shadow 佈局
可經過如下代碼來去掉動畫
// 設置一個空的 shadowImage 來實現
self.navigationController.navigationBar.shadowImage = [UIImage new];
複製代碼
那麼有同窗可能要問了,一直透明的能夠經過上述方法來實現,那若是想要隨着 上拉距離的改變,實現其透明度動態變化要怎麼作?ui
// 這個就要監聽 scrollView 的 offset
// 而後獲取到 NavigationBar複合視圖 的顯示子控件,動態改變其透明度
[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = 0;
複製代碼
既然講到這裏了就說下來回 push 或 pop,以及使用手勢來返回的時候,上下層級之間 NavigationBar 隱藏與否的設置,由於若是這裏沒處理好的話,會有一個黑條,或者直接顯示下一層級的視圖,體驗特別差,這時候就須要經過動畫的方式的在下一層級進行設置spa
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// 當前 VC 須要顯示 navigationBar 就設置爲 NO,須要隱藏就設置爲 YES
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
複製代碼
#warning 這時候就須要在當前 VC 中設置手勢代理了
self.interactivePopGestureRecognizer.delegate = self;
// 實現代理方法:返回 YES,則手勢有效
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
//當導航控制器的子控制器個數 大於1 手勢纔有效
return self.childViewControllers.count > 1;
}
複製代碼
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];
}
複製代碼
若是要實現以下效果的導航欄,設置 leftBarButtonItems 和 rightBarButtonItems 便可 3d
關於 rootVC 的 offset,先來看幾個 ViewController 的屬性 代理
iOS7之後默認設置是 UIRectEdgeAll,translucent 的默認值是 true,這個組合會使 rootView 的佈局從 (0, 0) 開始,就會形成 rootView 被 NavigationBar 遮擋住一部分,將 edgesForExtendedLayout 設置爲 UIRectEdgeNone 便可解決問題code
automaticallyAdjustsScrollViewInsets 默認值是 YES,表示在全屏下會自動將 第一個添加到 rootVC 的 ScrollView 的 contentInset 設置爲 (64, 0, 0, 0),這樣 scrollView 就不會被導航欄遮擋住了cdn
項目中有個需求是A push 到 B, B push 到 C, C pop 到 D,D 再 pop到 A,就比如這樣:
[self.navigationController pushViewController:B animated:YES];
// 此時 self.navigationController.childViewControllers = [A, B];
複製代碼
[self.navigationController pushViewController:C animated:YES];
// 此時 self.navigationController.childViewControllers = [A, B, C];
複製代碼
// 創建可變拷貝對象,而後進行替換操做
NSMutableArray *navChildMArr = [self.navigationController.childViewControllers mutableCopy];
[navChildMArr replaceObjectAtIndex:1 withObject:D];
// 固然,最後再將替換後的數組賦值回去不要忘了
[self.navigationController setViewControllers:navChildMArr animated:YES];
#warning 至於寫上面這串代碼的時機:寫在 B push C 以後能夠,寫在 C 的 viewDidLoad() 方法中也能夠
複製代碼
最後的效果如圖
若是有其餘問題,能夠在留言處寫下來,不按期更新