高级Auto Layout笔记

作者: liushuaikobe | 来源:发表于2016-07-08 12:46 被阅读479次

    1. 布局过程

    在使用了Auto Layout情况下,View显示到屏幕上分为3个阶段:

    1. 约束计算:发生自子View->父View。通过显式调用setNeedsUpdateConstraints来触发这个过程,实际上更改约束会自动触发这个过程。在自定义View中,可以覆盖updateConstraints来添加或变更约束。
    2. 布局:发生自父View->子View。将1中计算的结果,应用到View的frame上。通过显式调用setNeedsLayout来触发这个过程,这个函数很廉价,因为所有的布局请求都会合并成一个layout过程去做。当然,可以通过调用layoutIfNeeded来迫使系统立刻更新布局。在自定义View中,可以通过覆盖layoutSubviews方法来hook这个过程。
    3. 展示:这个过程与是否使用了Auto Layout无关。发生自父View->子View。通过显式调用setNeedsDisplay来触发这个过程,视图的绘制过程也会被合并。类似地,可以覆盖drawRect:来hook这个过程。

    以上三个阶段是依次发生的,每一步都会依赖它的前一步。要注意,以上三个阶段这是一个迭代的过程,比如布局阶段可能触发了另一个约束计算的过程,这个计算过程又触发了新的布局过程等等。

    2. Intrinsic Content Size

    Intrinsic这个词的意思,「本质的、固有的」。一个View的Intrinsic Content Size意指这个View想要舒舒服服地显示出来,需要多大的size。对于一个numberOfLines为0的Label来说,它的preferredMaxLayoutWidth确定、font确定,则它的intrinsicContentSize就定下来了。不是所有的View都有intrinsicContentSize,在自定义的View中,可以覆盖intrinsicContentSize方法来返回Intrinsic Content Size,并可以通过调用invalidateIntrinsicContentSize来通知布局系统在下一个布局过程采用新的Intrinsic Content Size。

    3. Compression Resistance 和 Content Hugging

    首先明确:这两个属性都是讨论的前提是View在相应的维度有Intrinsic Content Size。实际上,这两个属性和Intrinsic Content Size都是被翻译成约束来实现的。举个例子(请务必多读几遍这个例子):假设一个Label的Intrinsic Content Size是{100, 30},它在水平和竖直方向上的Compression Resistance优先级是750,在水平和竖直方向的Content Hugging优先级是250,那么这些被转成了如下约束:

    H:[label(<=100@250)]
    H:[label(>=100@750)]
    V:[label(<=30@250)]
    V:[label(>=30@750)]
    

    4. Alignment Rect

    Auto Layout操作的是View的Alignment Rect,不是View的Frame。这是个伟大的概念,用于把View的布局和显示解耦,虽然大部分情况它们是相等的。同样,View的Intrinsic Content Size也指的是Alignment Rect。在View有阴影、自定义Badge时,这个概念会很有用。在自定义的View中,可以通过覆盖alignmentRectInsets,来返回在特定的Frame下,Alignment Rect的edge insets是多少。还可以覆盖alignmentRectForFrame:frameForAlignmentRect:来实现更精细的控制,蛋这两个方法必须互为反函数。

    5. 其它

    1. 如果自定义的View是基于Auto Layout封装,那么它就不能在未开启Auto Layout的Window上使用,因此最好覆盖View的requiresConstraintBasedLayout,返回YES来宣称这件事。
    2. 程序挂掉:'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. 原因通常因为是我们在第2个阶段(布局阶段)更改了约束,这通常是在被覆盖的layoutSubviews方法里做的,这触发了第1个阶段,但是却没有再次触发布局阶段。通常的解决办法是在更改约束后再次调用[super layoutSubviews]来显式触发布局过程。
    3. Auto Layout的性能:http://floriankugler.com/2013/04/22/auto-layout-performance-on-ios/

    原文链接:http://blog.liushuaiko.be/blog/2016/07/09/advanced-autolayout/

    donate1.png

    相关文章

      网友评论

      本文标题:高级Auto Layout笔记

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