UINavigationController的使用

每个导航控制器会有一个根控制器,通过初始化方法设置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 有效。

/** 禁用ContentInset自动调整*/
- (void)disableAutoAdjustContentInsetForScrollView {
    if (@available(iOS 11.0, *)) {
        self.introductionTextView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
}

安全区(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视图的标题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容