美文网首页IOS
UINavigationController详解

UINavigationController详解

作者: 书上得来终觉浅 | 来源:发表于2019-08-04 18:51 被阅读0次

    1 概述

    UINavigationController继承自UIViewController,是一个基于栈的容器型控制器。既然是容器,它就能装一些东西,比如UIView能装各种组件(UILabel,UIButton等),UINavigationController装的是视图控制器。

    一个UINavigationController包含了几个部分,

    • Navigation Stack导航栈,它以栈的形式来管理视图控制器。栈的一个视图控制器(栈底),称为根视图控制器,其他称为子视图控制器。栈中的控制器可以通过self.navigationController找到UINavigationController的实例。

    • UINavigationBar导航条,栈中的视图控制默认会在顶部加一个导航条,虽然Navigation Bar显示在子视图控制器的界面上,但是它是由UINavigationController实例管理的,不过,导航条的内容却是由子视图控制器决定(通过self.navigationItem设置)。

    • UIToolbar工具栏,UINavigationController在子视图的底部提供了工具栏,默认不显示,也很少用到。

    2 Navigation Stack导航栈

    UINavigationController的作用是以栈的方式管理UIViewController,所以方法基本上是围绕进出栈的。

    • 进栈方法

      当子视图控制器拿到UINavigationController的实例引用后,使用下列方法推控制器进栈:

      - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
      

      上面的进栈方法是最常用的,它将当个viewController推入栈中,如果要一次性设置多个viewController进栈,可以使用下面的方法:

      - (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated
      

      因为UINavigationController在一个时刻只能显示一个视图控制器,当设置了多个viewController时,显示栈顶的视图控制器。

    • 出栈方法

      - (UIViewController *)popViewControllerAnimated:(BOOL)animated; 
      - (NSArray<UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
      - (NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated; 
      

      UINavigationController有3中出栈方式,第一个是移除当前的子视图控制器,第二个是返回到指定的子视图控制器,UINavigationController会移除目标控制到栈顶之前的所有视图控制器。第三个是返回到栈底(根视图控制器)。

    3 导航栏显示与隐藏

    导航栏显示与否是UINavigationController控制的,NavigationController提供了如下方法显示与隐藏导航栏。

    - (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated; 
    

    4 UINavationBar 导航条

    导航条比较特别,它的创建,配置和显示是由UINaviagtionController负责的,而内容是由子视图控制器提供的,具体是navigationItem。

    4.1 导航条内容定制

    导航条的内容是由当前子视图控制器的navigationItem属性确定的,内容主要分为左边项,标题项以及右边项。

    4.1.1 左边按钮定制

    除了根视图控制器,在栈中的其他子视图控制器中,导航条的左边存在一个返回按钮,定制这个按钮的规则如下:

    • 如果当前栈顶的视图控制器定义了navigationItem.leftBarButtonItem属性,则以当前定义的为准。
    • 否则,如果上一个视图控制器定义了navigationItem.backBarButtonItem属性,则以上一个视图控制器定义的为准
    • 如果当前视图控制器为定义leftBarButtonItem属性,上一个视图控制器也没有定义backBarButtonItem。则以上一个视图控制器的title属性为准

    navigationItem还有一个属性是leftBarButtonItems,它允许用户定义一个按钮集合放在导航条的左边。

    4.1.2 标题定制

    UINavigationController根据下面的顺序更新导航栏的标题项:

    • 栈顶视图控制器使用navigationItem.titleView自定义标题时,优先使用titleView
    • 否则,导航栏标题使用一个UILabel作为标题,内容从视图控制器的title属性中获取。

    titleView是UIView的实例,也就是说标题可以是任意UIView的子类,上面的UILabel也是UIView的子类。

    4.1.3 右边按钮定制

    栈顶视图控制器设置了navigationItem.rightBarButtonItem时,UINavigationController会将其设置内容更新在导航栏的右边,如果没有设置,则在导航栏的右边不显示任何内容。

    leftBarButtonItem、rightBarButtonItem以及backBarButtonItem都是UIBarButtonItem类型的。也就是说,如果我们要在导航条上定义按钮,就得使用UIBarButtonItem对象,如果系统提供的UIBarButtonItem的属性满足不了我们的需求,可以使用UIBarButtonItem.customView属性来包裹我们指定的视图。

    4.2 导航栏的外观定制

    导航栏的外观定制有两种方式,一种是通过navigationBar的实例定制,另一种是通过UIAppearance来获取实例类的外观代理对象定制外观,UIAppearance是一个协议(Protocol),实现了这个协议的类可以通过它的appearance方法获取这个类的外观代理,UIView已经实现了这个协议。通过UIAppearance外观代理类设置的外观是全局性的。

    4.2.1 BarStyle导航条样式

    导航栏默认有两种标准的显示样式:白底黑字和黑底白字,可以通过navigationBar.barStyle属性设置。

    //把app中的所有导航条都设置为黑底白字
    [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
    
    //把myNavController下的导航条设置为黑底白字的样式,其他navigationController中的不会改变
    [myNavController.navigationBar setBarStyle:UIBarStyleBlack]
    

    4.2.2 translucent 透明度

    导航条默认是半透明的(translucent),可以设置起为不透明,

    [[UINavigationBar appearance] setTranslucent:NO];
    

    需要注意的是,translucent=YES时,子视图控制器的self.view的原点在整个屏幕中的位置是导航栏的左上方(这个好理解,因为导航栏是透明的,有点像css的绝对定位,所以控制器的view会顶上去,那么原点的位置就发送了变化),当translucent=NO时,控制器的self.view的原点在屏幕中的位置在导航栏的左下方。

    当translucent=YES时,可设置控制器的edgesForExtendedLayout属性来改变view的原点在屏幕中的位置

    //从navigationBar下面开始计算一直到屏幕tabBar上部
    self.edgesForExtendedLayout = UIRectEdgeNone;
    //从屏幕边缘计算(默认)
    self.edgesForExtendedLayout = UIRectEdgeAll; 
    //navigationBar下面开始计算一直到屏幕tabBar上部
    self.edgesForExtendedLayout = UIRectEdgeTop;
    //从navigationBar下面开始计算一直到屏幕底部
    self.edgesForExtendedLayout = UIRectEdgeBottom;
    

    4.2.3 导航栏的字体与颜色

    导航栏的字体与颜色分别由以下几个属性控制:

    导航栏字体与颜色
    • barTintColor 导航栏背景色,前面我们说了,barStyle有两种样式白底和黑底,如果设置了barTintColor的值,这个值会覆盖barStyle设置的背景色。

      //设置导航栏的背景色
      [[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
      
    • tintColor 按钮颜色

      //按钮颜色
      [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
      
    • titleTextAtrributes 标题的样式,通过NSAttributedStringKey查看可设置的属性

       NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor blackColor],
                              NSForegroundColorAttributeName,
                              [UIFont boldSystemFontOfSize:18.0],
                              NSFontAttributeName,nil];
       [UINavigationBar appearance].titleTextAttributes = dic;
      

    4.2.4 导航栏透明

    是导航栏完全透明可以设置背景图片和阴影图片两个属性。按照业务需求,一般只有个别的页面要求导航栏透明,所以这不使用全局设置,而在具体的ViewController中设置

    [self.navigationController.navigationBar setBackgroundImage:[UIImage new]
                                                  forBarMetrics:UIBarMetricsDefault];
    self.navigationController.navigationBar.shadowImage = [UIImage new];
    //通常导航栏透明,需要上移self.view原点的位置,这里还设置了translucent
    self.navigationController.navigationBar.translucent = YES;
    

    相关文章

      网友评论

        本文标题:UINavigationController详解

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