UINavigationController 層級關係及一些常用設定
UINavigationController一直是iOS開發中最常用的控制元件之一,但是一般就是工程開始時對其做一些統一的處理。後期操作就比較少了。導致雖然其很常用但是我們的熟悉程度卻不是很高。今天就來記錄一下我們常用的這個控制元件.
UINavigationController繼承自UIViewController,是一個基於棧的容器型控制器。既然是容器,他就能裝一些東西。比如UIView能新增一些子檢視,UINavigationController裝的就是檢視控制器。
一個UINavigationController包含了幾個部分:
1.Navigation Stack 導航棧,它以棧的形式來管理檢視控制器。棧的一個檢視控制器(棧底),稱為根檢視控制器,其他稱為子檢視控制器。棧中的控制器可以通過self.navigationController找到UINavigationController的例項。
2.UINavigationBar導航條 棧中的檢視控制器會在頂部加一個導航條,雖然NavigationBar顯示在子檢視控制器的介面上,但是它是由UINavigationController例項管理的,不過導航條的內容卻是由子檢視控制器來決定的(通過self.navigationItem設定)
3.UIToolbar工具欄,UINavigationController在子檢視的底部提供了工具欄,預設不顯示,也很少用到。
常用的屬性
// 棧頂VC @property(nullable, nonatomic,readonly,strong) UIViewController *topViewController;// 如果存在模態檢視控制器則返回模態檢視控制器,否則頂檢視控制器。 @property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController; // 導航控制器目前棧中所管理的VC @property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers; // 導航欄是否隱藏 @property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;// 導航欄 @property(nonatomic,readonly) UINavigationBar *navigationBar; // 工具欄是否隱藏, 預設為YES @property(nonatomic,getter=isToolbarHidden) BOOL toolbarHidden // 工具欄 @property(null_resettable,nonatomic,readonly) UIToolbar *toolbar
手勢相關的屬性
// 返回手勢識別器 @property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer // 屬性為YES時,當鍵盤出現時,導航控制器的navigationBar工具欄將被隱藏。當鍵盤關閉時,這些條將保持隱藏狀態,但只要在內容區域輕擊一下,就會顯示它們。 @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears // 當用戶滑動時,導航控制器的導航欄和工具欄將被隱藏(向上滑動)或顯示(向下滑動)。工具欄只有在有專案時才參與。 @property (nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe // 手勢識別器,如果滑動條將隱藏或顯示,它將觸發該手勢識別器。不要更改委託或試圖通過覆蓋此方法來替換此手勢。 @property (nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer NS_AVAILABLE_IOS(8_0) // 當UINavigationController的垂直大小類是緊湊的時,隱藏UINavigationBar和UIToolbar。 @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact // 當用戶點選時,導航控制器的navigationBar & toolbar將被隱藏或顯示,這取決於導航欄的隱藏狀態。工具欄只有在有要顯示的專案時才會顯示。 @property (nonatomic, readwrite, assign) BOOL hidesBarsOnTap // 手勢識別器,用於識別由於內容的點選而隱藏或顯示的bar。不要更改委託或試圖通過覆蓋此方法來替換此手勢。 @property (nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer
常用的方法
// 推進一個VC (壓棧操作) - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated; // 彈出導航控制器所管理的當前VC,返回值為彈出的檢視控制器 - (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated; // 彈出檢視控制器,直到指定的在頂部。返回彈出的控制器。 - (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated; // 直到堆疊上只剩下一個檢視控制器。返回彈出的控制器。 - (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated; // 設定導航控制器所管理的VC 陣列,如果動畫是YES,那麼根據新的top檢視控制器是否先前在堆疊中模擬push或pop。 - (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated
UINavigationControllerDelegate
//即將展示檢視控制器時呼叫 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated; //已經展示檢視控制器時呼叫 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated; //螢幕旋轉時 NavigationController 支援的方向 - (UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(tvos); //自控制器支援的方向 /** 子控制器支援的方向 * UIInterfaceOrientation 列舉型別 * 1. UIInterfaceOrientationUnknown 裝置的朝向不能確定。 * 2. UIInterfaceOrientationPortrait 該裝置處於豎屏模式,裝置保持直立,底部的Home鍵。 * 3. UIInterfaceOrientationPortraitUpsideDown 該裝置處於豎屏模式,但上下顛倒,裝置保持直立,頂部的Home鍵。 * 4. UIInterfaceOrientationLandscapeLeft 裝置處於橫向模式,裝置保持直立,右側Home鍵。 * 5. UIInterfaceOrientationLandscapeRight 該裝置處於橫向模式,裝置保持直立,左側Home鍵。 */ - (UIInterfaceOrientation)navigationControllerPreferredInterfaceOrientationForPresentation:(UINavigationController *)navigationController API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(tvos); //自定義轉場動畫 - (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController API_AVAILABLE(ios(7.0)); //自定義轉場動畫 - (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC API_AVAILABLE(ios(7.0));
常用的設定
想要改變Bar的背景顏色可以這樣設定
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
取消半透明效果
self.navigationController.navigationBar.translucent = NO;
改變NavigationBar的標題顏色 和 字型大小
NSDictionary *dic = [NSDictionary dictionaryWithObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
self.navigationController.navigationBar.titleTextAttributes = dic;
隱藏NavigationBar
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:YES animated:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self.navigationController setNavigationBarHidden:NO animated:animated]; }
想要改變NavigationBar的前景顏色 也就是所有UIBarButtonItem的字型顏色可以如下設定
self.navigationController.navigationBar.tintColor = [UIColor redColor];
單獨設定
self.navigationItem.leftBarButtonItem.tintColor = [UIColor grayColor];
當tableView等滑動時是否隱藏NavigationBar
self.navigationController.hidesBarsOnSwipe = YES;
當檢視接受點選時 是否隱藏NavigationBar
self.navigationController.hidesBarsOnTap = YES;
當鍵盤出現時是否隱藏NavigationBar
self.navigationController.hidesBarsWhenKeyboardAppears = YES;
當螢幕改變方向時是否隱藏NavigationBar
self.navigationController.hidesBarsWhenVerticallyCompact = YES;
當檢視被push完之後 是否隱藏NavigationBar
self.navigationController.hidesBottomBarWhenPushed = YES;
UINavigationController的層級
我們建立一個簡單的帶UINavigationController的工程 看一下他們的層級 工具 Xcode11 模擬器iphone11
從層級我們能清楚的看到UINavigationBar(層級選中的狀態)及下層的子控制元件是我們需要操作的單元,但是從官方給我們留出來的介面來看 我們很難拿到Bar的子控制元件。
上面的是最原始的Bar 我們可以加上一個標題再看一下.
我們可以看到登陸這個Label在Bar下的第一級子試圖 而且在最上層 對原始狀態的Bar下的檢視除了遮擋沒有產生任何影響
可以看到我們設定UINavigationBar的背景顏色是不會有效果的,因為其前面還有幾個檢視擋著Bar。