美文网首页iOS点点滴滴
iOS11 自定义导航栏衍生的几个问题(高度、间距等)

iOS11 自定义导航栏衍生的几个问题(高度、间距等)

作者: 游龙飞雪 | 来源:发表于2018-02-10 14:51 被阅读535次

    本文讨论的问题:

    1. 自定义导航栏,导航栏高度;
    2. items 与导航栏间的间距;
    3. 导航栏的层次结构;
    4. 自定义导航栏的一大好处!

    正文:

    有个项目中自定义导航栏,当然是继承自 UINavigationBar ,但是显示效果与期望值不符,上移了一段距离(20px)。如下图:


    image.png

    首先想到的是调整frame的高度,运行之后仍没有效果。
    于是想到查看一下视图的层次结构。如下图:

    image.png

    如图所示的层次结构,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。

    解决思路:

    1. 在自定义navBar中重写 layoutSubviews 方法;
    2. 调用父类 super.layoutSubviews() 让系统布局完毕;
    3. 遍历 navBar 的 subViews 找到 视图background 和 视图contentView;
    4. 分别设置它们的frame;
    5. 当然有个前提,那就是要先判断当前系统版本,如果 versionCode > 11.0 才需要自己处理。
    6. 还要注意一个问题,那就是 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(多个按钮之间的间距)

    相关文章

      网友评论

        本文标题:iOS11 自定义导航栏衍生的几个问题(高度、间距等)

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