美文网首页
UINavigationController的使用

UINavigationController的使用

作者: 高思阳 | 来源:发表于2018-10-18 14:01 被阅读10次

    每个导航控制器会有一个根控制器,通过初始化方法设置initWithRootViewController,这个初始化方法会调用pushViewController:animated:方法push根控制器,因此自定义导航控制器重写pushViewController:animated:方法的时候,要考虑到初始化时,对根控制器也会调用。

    导航栏遮盖视图问题

    iOS7 之前:

    • UINavigationBar 的 translucent 属性默认 NO。 (导航栏默认完全不透明)

    iOS7 之后:(view controllers默认使用全屏布局(full-screen layout))

    • UINavigationBar 的 translucent 属性默认 YES。(导航栏默认半透明)
    • UIViewController 多了 extendLayoutIncludesOpaqueBars(default: NO)属性。
    • UIViewController 多了 edgesForExtendedLayout(default: UIRectEdgeAll)属性。
      说明:extendLayoutIncludesOpaqueBars 延伸布局是否包括不透明的 bar ; edgesForExtendedLayout 延伸布局的样式,默认上下左右全部延伸。

    注意:当translucent=NO的时候,不管edgesForExtendedLayout设置成UIRectEdgeAll还是UIRectEdgeNone,view都是从导航栏底部开始
    那么问题来了,怎么让translucent=NO的时候,view也能从(0,0)开始布局呢?
    苹果也考虑到了这种需求,提供了 extendedLayoutIncludesOpaqueBars 这个属性。extendedLayoutIncludesOpaqueBars 默认值是NO,下面把它改为YES

    问题:

    • 导航栏默认会遮蔽视图,因为视图默认布局为全延伸。

    解决方案:

    1. 设置(个人用的少)self.navigationController.navigationBar.translucent = NO;
    2. 设置self.edgesForExtendedLayout = UIRectEdgeBottom | UIRectEdgeLeft | UIRectEdgeRight;或者self.edgesForExtendedLayout = UIRectEdgeNone(视图布局时不向任何方向延伸)

    设置导航栏标题

    方法一:在UIViewController中设置self.title。
    方法二:设置self.navigationItem.titleView。

    automaticallyAdjustsScrollViewInsets

    还有一个属性:

    • automaticallyAdjustsScrollViewInsets:
      默认值YES,表示在全屏模式下会自动修改第一个添加到 rootView 的 scrollview 的 contentInset 为(64,0,0,0)
      先设置automaticallyAdjustsScrollViewInsets为NO
      automaticallyAdjustsScrollViewInsets在iOS11中已废弃,需要使用ScrollView子类的contentInsetAdjustmentBehavior属性来代替(比如写成self.tableView.contentInsetAdjustmentBehavior=UIScrollViewContentInsetAdjustmentNever;)

    需要注意的是automaticallyAdjustsScrollViewInsets=YES只对VC第一个添加到 rootView 的 scrollview 有效。

    安全区(safeArea)
    在iOS11 中引入了安全区的概念,说白了就是:你放在这个区域里面的视图是不会被NavigationBar和TabBar和StatusBar遮住的.(前提是你不去手动修改安全区范围的情况下),安全区本身不是一个View,不会显示在我们的视图层级上,只是给你参考用.

    safeAreaInset属性
    iOS11之前,如果有tableview向下偏移64的情况的话.64这个值是在contentInset里面获取的,iOS11之后改成了从safeAreaInset获取.但是contentInset这个属性 !!!!依旧是有用的,并没有废弃. !!!!
    contentInsetAdjustmentBehavior属性
    上面的说过的automaticallyAdjustsScrollViewInsets属性在iOS 11中已经被废弃了(设置这个没用了),改用UIScrollview子类的contentInsetAdjustmentBehavior属性来代替例如

    self.tableview.contentInsetAdjustmentBehavior=UIScrollViewContentInsetAdjustmentNever;//使用这行代码来代替
    contentInsetAdjustmentBehavior//属性有4个枚举值:
    {
      UIScrollViewContentInsetAdjustmentAutomatic:在有导航栏的VC中,这个属性会设置上部和底部的adjustedContentInset值,方式为adjustedContentInset = safeAreaInset + contentInset。其他情况下与UIScrollViewContentInsetAdjustmentScrollableAxes相同
    
      UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滚动方向上adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上adjustedContentInset = contentInset
    
      UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset
    
      UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset
    }
    

    四、UINavigationBar和UINavigationItem

    • UINavigationBar和UINavigationItem的区别

    1、UINavigationBar的功能类似于UINavigationController中的栈,UINavigationController管理的是控制器的栈,而UINavigationBar管理的是UIBarButtonItem。在UINavigationController中有一个UINavigationBar类的属性-navigationBar,查看这个属性(@property(nonatomic,readonly) UINavigationBar *navigationBar; // The navigation bar managed by the controller. Pushing, popping or setting navigation items on a managed navigation bar is not supported.),虽然在UINavigationBar中有push、pop NavigaitonItem的方法,但我们看到在属性后又这样注释:“这个navigationbar是通过控制器来管理的,它本身不支持pushing,poping或者setting 一个navigationbar”,说明在一个导航控制器UINavigationController里,UInavigationItem的pop、push方法是由系统自动管理的,我们仅需知道UINavigationController push或者pop一个控制器的同时,UInavigationBar也在对应的push和pop UINavigationItem,导航栏和控制器是一一对应的同步关系。(因此UInavigationBar里面有push和pop UINavigationItem的方法,但是这些方法是用在单独使用UInavigationBar的时候)
    2、UINavgationItem管理着显示在UINavigationBar上的按钮和图片,每一个push进栈的控制器都会自带一个navigationbar,navigationbar要实现显示图片和button,就需要通过UINavtionItem完成。为了验证以上说法,我们也可以查看UINavigationItem的类属性,UINavigationItem包含了NavigaitonBar视图的全部元素(如title,tileview,backBarButtonItem等,同时又受当前栈顶控制器管理,即NavigaitonBar形成整个NavigationController的导航视图,然后每个NavigationController页面的导航栏元素由所在页面的UINavigationItem管理。简单的概括:控制器视图中的导航栏显示由UINavigationBar和UiNavigationItem共同完成,在控制器进行跳转时,UINavigationBar管理导航栏与栈顶控制器的对应关系,而UINavigationItem管理导航栏的显示内容。

    1、UINavigationBar
    tintColor barTintColor 分别在iOS7和它之前的区别

    iOS7以前:
    tintColor:设置navigationBar和navigationItem的颜色,navigationItem里面的字体默认为白色,如果想修改navigationItem字体颜色,需要自定义给navigationItem(Custom)。

    iOS7之后(新增barTintColor属性):
    tintColor:不再是以前的设置navigationBar和navigationItem的颜色,而是变成了只修改navigationItem里面的字体颜色。
    barTintColor:设置navigationBar和navigationItem的颜色,由于iOS7的navigationItem以文字的方式体现,默认为蓝色,所以barTintColor看似乎对navigationItem无效。

    2、UINavigationItem

    • iOS11下自定义leftBarButtonItem大小改变的问题修复
      一般leftBarButtonItem加载网络图片或因为其他问题,必须要在leftBarButtonItem使用自定义的UIButton时,就会因为图片太大,导致设置为UIButton的背景图片时,因为图片太大,拉宽leftBarButtonItem(为了解决这个问题,只需要在button的外层包装一层view即可)
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 15, 15)];
    UIView *leftCustomView = [[UIView alloc] initWithFrame: btn.frame];
    [leftCustomView addSubview:btn];
    [btn setImage:[UIImage imageNamed:@"123"] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
    viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:leftCustomView];
    
    • 两种设置当前viewController中navigationItem的barButtonItem方法
      第一种是在viewController控制器内部设置(最好是在baseViewController里面设置,这样继承自baseViewController的控制器,可以通过重写设置控制器样式的方法,修改自己的控制器样式。)
      第二种是在自定义的UINavigationcontroller里面-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated方法中统一设置

    • leftBarButtonItem与backBarButtonItem的区别
      从显示的优先级来讲(假如现在即将从A视图跳到B视图,从B视图角度说):
      1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;
      2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项(依然是一个后退按钮,自定义的部分只有背景或title);
      3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。

    相关文章

      网友评论

          本文标题:UINavigationController的使用

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