1. 程式人生 > 實用技巧 >UINavigationController 層級關係及一些常用設定

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。