iOS11 自定义导航栏衍生的几个问题(高度、间距等)
本文讨论的问题:
- 自定义导航栏,导航栏高度;
- items 与导航栏间的间距;
- 导航栏的层次结构;
- 自定义导航栏的一大好处!
正文:
有个项目中自定义导航栏,当然是继承自 UINavigationBar ,但是显示效果与期望值不符,上移了一段距离(20px)。如下图:
image.png
首先想到的是调整frame的高度,运行之后仍没有效果。
于是想到查看一下视图的层次结构。如下图:
如图所示的层次结构,navbar 下面有两个直接子视图,background 和 contentView。
而navBar的高度时正确的,只是background和contentView上移了。而且这俩家伙的高度也与期望的不相符。
(background)
image.png
(contentView)
image.png
通过打印的内容可以看出,background 和 contentView 的高度都是44,比预期的64减小了20,正好是一个状态栏的高度。
有个思路是将它们下移 20 。
根据视图层次,我们知道background是负责渲染背景相关的,contentView负责显示我们设置的控件、title等内容。
所以,为了使导航栏与状态栏的风格一致,
决定将 background 的高度从 44 变为 64,与导航栏一致;
将 contentView 下移 20 。
怎么才能拿到这两个视图呢?方法是遍历导航栏navBar的子视图 subViews。
那么在什么时机遍历子视图-修改frame合适呢?
还是在 自定义navBar 的 layoutSubviews 方法中最合适。
注意在 自定义navBar 中重写 layoutSubViews 方法时,要先 super.layoutSubviews() 一下,否则会导致自定义导航栏中没有东西,因为系统没给layout。
解决思路:
- 在自定义navBar中重写 layoutSubviews 方法;
- 调用父类 super.layoutSubviews() 让系统布局完毕;
- 遍历 navBar 的 subViews 找到 视图background 和 视图contentView;
- 分别设置它们的frame;
- 当然有个前提,那就是要先判断当前系统版本,如果 versionCode > 11.0 才需要自己处理。
- 还要注意一个问题,那就是 iPhone X 设备,需要为此单独设置frame。
为了清晰明了,直接上代码:
image.png
设置完毕,运行,效果如下:
image.png
有没有发现上面这张图的 Left 按钮跟第一张图的 Left 按钮的区别?
是的,这就是要继续讨论的【2. items 与导航栏间的间距 】这个问题。
我们都有过这样的感觉,设置完 leftBarButtonItem 或者 rightBarButtonItem 的时候,总感觉它距离屏幕的边距有点远。
在iOS10之前,要使边距近一点,是在它俩之间添加一个 "占位" ,并设置占位item的宽度width = -15; 对是负的,如下:
【
UIBarButtonItem *leftFixed = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
leftFixed.width = -15;
】
image.png
而在 iOS11 之后,这样设置不起作用了。
根据视图层次结构,之后设置 导航栏的 barContentView 的内边距小一点,于是就有了这行代码:
【 view.layoutMargins = UIEdgeInsetsMake(0, 2, 0, 2) 】
OK,虽然显示在导航栏里的东西设置完了,也显示正常了,但是还有一个问题没有讨论,那就是自定义导航栏的一大好处!
先来看效果:
image.png
这个效果避免了与大多数App那样前后两个页面的导航栏融合在一起混乱的感觉,这样子多么清爽!
So,自定义导航栏的一大作用就是在push或者pop时前后两个导航栏相互独立,看起来清爽宜人!
附:导航栏结构类名
UINavigationBar
** _UIBarBackground
****** UIImageView
****** UIImageView
** _UINavigationBarContentView
****** _UIButtonBarStackView(left)
********** _UITAMICAdaptorView(左侧按钮)
********** UIView(多个按钮之间的间距)
********** _UIButtonBarButton
****** _UIButtonBarStackView(right)
********** _UITAMICAdaptorView
************** UIButton(右侧按钮)
********** UIView(多个按钮之间的间距)
********** _UITAMICAdaptorView
********** UIView(多个按钮之间的间距)