美文网首页iOS的路上
UINavigationController

UINavigationController

作者: 雪山飞狐_91ae | 来源:发表于2018-03-22 19:19 被阅读142次

    UINavigationController

    • UINavigationController继承自UIViewController,用来展示具有明显的层级结构的内容,让我们更高效的将层级结构的内容展现给用户。在每个层级中用一个UIViewController来展示具体内容。下面的图是iOS设备中的设置界面的图:


      iOS设备的设置

    UINavigationController是一个容器视图控制器,其内部展示着多个UIViewController的内容。UINavigationController的View由三个部分组成,最上面的UINavigationBar,最下面默认隐藏的toolbar,以及中间部分的UIViewController的View。


    UINavigationController的层级结构

    UINavigationController的堆栈管理

    • UINavigationController通过其管理的一个UIViewController堆栈来决定中间的View显示什么。中间的View显示的是UIViewController堆栈顶部的UIViewController的View。


      UINavigationController
    • 理解上面这幅图很重要。我们看到UINavigationController拥有viewControllers,navigationBar,toolBar这些属性。其中viewControllers是一个数组,在这个数组中以堆栈的形式存放着多个UIViewController。堆栈是先进后出的原则。UINavigationController的中间的View显示的是位于堆栈顶部的UIViewController的View。
    • 位于堆栈最底部的UIViewController我们称之为rootViewController(根视图控制器),一个UINavigationController的UIViewController堆栈中至少有一个视图控制器,也可以说一定存在根视图控制器。我们可以创建一个UIViewController,然后使用系统提供的方法让这个UIViewController进栈,也可以使用系统提供的方法让UIViewController堆栈中的视图控制器出栈。

    UINavigationController的创建

    创建UINavigationController的方法:

    //创建一个视图控制器
    FirstPageViewController *VC = [[FirstPageViewController alloc] init];
    //把上面创建的视图控制器作为根视图控制器创建一个UINavigationController
    //这样UINavigationController的UIViewController堆栈中已经有了一个视图控制器即VC,这时候UINavigationController的中间那部分的View显示的是VC的View。
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:VC];
    

    当我们想要进入这个UINavigationController的页面时可以:
    [self presentViewController:navigationController animated:YES completion:^{}];

    UIViewController的进栈和出栈

    • 进栈:
      [self.navigationController pushViewController:VC animated:YES];
      示例代码:
        //我们有一个继承自UIViewController的类SecondPageViewController,创建该类的实例VC
        SecondPageViewController *VC = [[SecondPageViewController alloc] init];
        //然后我们使用系统的方法pushViewController:animated:使VC进入navigationController的UIViewController堆栈。
        //此时这个堆栈中的栈顶元素变成了VC,因此navigationController的View部分展示的内容就变成了VC的View,所以画面进行了切换
        [self.navigationController pushViewController:VC animated:YES];
    
    • 出栈
    1. 使UIViewController中最顶层的元素出栈
      [self.navigationController popViewControllerAnimated:YES];
      执行这句话后,UIViewController中最顶层的元素出栈,所以堆栈中处于栈顶的元素发生了变化,navigationController中间的View也发生了变化,直观感觉就是退回了上一个页面。但是当堆栈中的元素只有一个时该方法无效,因为该堆栈中必须要保证至少要有一个元素。
    2. pop到指定的元素
      假设现在UIViewController堆栈中有四个元素,从栈底到栈顶依次是VC1,VC2,VC3,VC4。我们现在正处在VC4的View中。那么现在我们想直接退到VC2的页面,可以这样做:
    [self.navigationController popToViewController:self.navigationController.viewControllers[1] animated:YES];
    

    这个方法实际上是使堆栈中这个指定的viewcontroller上面的元素全部出栈,这样这个指定的viewcontroller就成了栈顶元素,直观感觉是回退到了这个视图控制器的页面。

    1. 直接pop到根视图控制器
      这个其实和上面的道理是一样的,就是使除栈底之外的其它视图控制器全部出栈,这样栈底的根视图控制器也是栈顶元素了。
      [self.navigationController popToRootViewControllerAnimated:YES];

    UINavigationBar

    • UINavigationBar是UINavigationController的View的上面的那部分。UINavigationController负责创建UINavigationBar。而UINavigationBar的内容则是由处于UIViewController堆栈顶部的UIViewController的navigationItem这个属性来管理的。

    UINavigationBar的外观管理

    • 1.设置style
        //设置bar的style
        self.navigationController.navigationBar.barStyle = UIBarStyleDefault;//这种设置是白底黑字
        self.navigationController.navigationBar.barStyle = UIBarStyleBlack; //这种设置是黑底白字
    
      1. 设置是否隐藏
        self.navigationController.navigationBar.hidden = YES;
    • 3.设置背景颜色
      self.navigationController.navigationBar.barTintColor = [UIColor redColor];
      1. 设置字体颜色
        self.navigationController.navigationBar.tintColor = [UIColor blackColor];
      1. 设置标题字体属性
    self.navigationController.navigationBar.titleTextAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:30], NSForegroundColorAttributeName: [UIColor whiteColor]};
    

    UINavigationBar的内容设置

    • 前面说过UINavigationBar的内容是由处于UIViewController堆栈栈顶的UIViewController的navigationItem属性来配置的。
    • UINavigationBar和navigationItem有什么联系?

    UINavigationBar是UINavigationController的属性,我们在设置了UINavigationBar的外观后,其将作用于全部的UIViewController。navigationItem是UIViewController的属性,它是配置这个UIViewController上面的UINavigationBar的内容的。UINavigationBar中有一个堆栈,这个堆栈是一个UINavigationItem堆栈,当把一个UIViewController push进栈的时候,它的navigationItem也会被push进UINavigationBar的堆栈。所以UINavigationBar的这个堆栈和这个UIViewController堆栈是一一对应的。

    UINavigationItem堆栈

    我们看到UINavigationBar有一个Items属性,这个items属性就是以堆栈的形式存放每个UIViewController的navigationItem。其中栈顶的navigationItem称为topItem,栈顶下面的item称为backItem。

    • UINavigationBar通过UINavigationItem堆栈按照如下方式来决定展示在UINavigationBar中的内容:
      位于中间的标题会按照下面的顺序展示内容:

    如果topitem设置了标题视图(titleview属性),则展示标题视图。
    如果topitem设置了标题文字(title属性),则显示标题文字。
    如果,什么也没有设置,则显示空白。

    位于右边的按钮按照下面的顺序展示内容:

    如果topitem设置了右侧按钮(rightBarButtonItem属性),则显示右侧按钮。
    如果没有设置右侧按钮,则显示空白。

    位于左侧的按钮会按照下列顺序显示内容:

    如果topitem设置了左侧按钮(leftBarButtonItem属性),则显示左侧按钮。
    如果backitem设置了返回按钮(backButtonItem属性),则显示返回按钮。
    如果backitem设置了标题文字(title属性),则显示利用标题文字封装的返回按钮。

    如果以上都未设置,则展示利用“Back”封装的返回按钮。

    tips

    在默认情况下返回按钮和左侧按钮是不同时显示的,默认是不显示左侧按钮,要使两者同时显示,可以设置:
    UINavigationBar通过UINavigationItem堆栈按照如下方式来决定展示在UINavigationBar中的内容

    tips

    修改返回按钮的标题
    //在这个页面设置,下个页面生效。
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"go" style:UIBarButtonItemStylePlain target:nil action:nil];

    设置返回按钮的图片:

    self.navigationController.navigationBar.backIndicatorImage = [UIImage imageNamed:@""];
    self.navigationController.navigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@""];
    

    这两句话必须同时设置才会生效。

    通过手势隐藏UINavigationBar与UIToolbar

    获取手势识别器

    // 侧滑返回手势识别器
    @property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer;
    // 用于轻拍隐藏UINavigationBar与UIToolbar的手势识别器
    @property(nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer;
    // 用于轻扫隐藏UINavigationBar与UIToolbar的手势识别器
    @property(nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer;
    // 示例
    UIGestureRecognizer *interactivePopGestureRecognizer = navigationController.interactivePopGestureRecognizer;
    

    隐藏UINavigationBar

    //这样设置是对堆栈中的所有viewcontroller生效
    //轻拍隐藏,再次轻拍显示
        self.navigationController.hidesBarsOnTap = YES;
    //向上轻扫隐藏,向下轻扫显示
        self.navigationController.hidesBarsOnSwipe = YES;
    //横屏隐藏(此时轻拍显示),竖屏显示.
        self.navigationController.hidesBarsWhenVerticallyCompact = YES;
    //键盘出现隐藏,键盘消失仍隐藏,但是轻点出现。
        self.navigationController.hidesBarsWhenKeyboardAppears = YES;
    

    相关文章

      网友评论

        本文标题:UINavigationController

        本文链接:https://www.haomeiwen.com/subject/lnwaqftx.html