136__iOS干货46__iOS布局总结

一,参考翻译范文:

https://juejin.im/post/5a951c655188257a804abf94

二,自动布局的三个步骤

第一步是更新约束

第二步是重新布局

第三步是重绘显示

三,布局

一个视图的布局指的是它在屏幕上的的大小和位置。每个 view 都有一个 frame 属性,用来表示在父 view 坐标系中的位置和具体的大小。UIView 给你提供了用来通知系统某个 view 布局发生变化的方法,也提供了在 view 布局重新计算后调用的可重写的方法

  1. UIview的方法layoutSubviews
    1. 这个 UIView 方法处理对视图(view)及其所有子视图(subview)的重新定位和大小调整。它负责给出当前 view 和每个子 view 的位置和大小。这个方法很开销很大,因为它会在每个子视图上起作用并且调用它们相应的 layoutSubviews 方法
    2. 不应该显示调用,应该触发使用,那样消耗更低
  2. UIViewController生命周期的layoutSubviews
    1. 当 layoutSubviews 完成后,在 view 的所有者 view controller 上,会触发  viewDidLayoutSubviews 调用。因为 viewDidLayoutSubviews 是 view 布局更新后会被唯一可靠调用的方法,所以你应该把所有依赖于布局或者大小的代码放在 viewDidLayoutSubviews 中,而不是放在 viewDidLoad 或者 viewDidAppear 中
  3. 自动刷新触发器
    1. 修改 view 的大小
    2. 新增 subview
    3. 用户在 UIScrollView 上滚动(layoutSubviews 会在 UIScrollView 和它的父 view 上被调用)
    4. 用户旋转设备
    5. 更新视图的 constraints
  4. 主动刷新触发器
    1. setNeedsLayout
      1. setNeedsLayout 方法会立刻执行并返回,但在返回前不会真正更新视图。视图会在下一个 update cycle 中更新,就在系统调用视图们的 layoutSubviews 以及他们的所有子视图的 layoutSubviews 方法的时候。即使从 setNeedsLayout 返回后到视图被重新绘制并布局之间有一段任意时间的间隔,但是这个延迟不会对用户造成影响,因为永远不会长到对界面造成卡顿
    2. layoutIfNeeded()
      1. 与 setNeedsLayout() 会让视图在下一周期调用 layoutSubviews 更新视图不同,layoutIfNeeded 会立即调用 layoutSubviews 方法。但是如果你调用了 layoutIfNeeded 之后,并且没有任何操作向系统表明需要刷新视图,那么就不会调用 layoutsubview。如果你在同一个 run loop 内调用两次 layoutIfNeeded,并且两次之间没有更新视图,第二个调用同样不会触发 layoutSubviews 方法
      2. 当对希望通过修改 constraint 进行动画时,这个方法特别有用。你需要在 animation block 之前对 self.view 调用 layoutIfNeeded,以确保在动画开始之前传播所有的布局更新。在 animation block 中设置新 constrait 后,需要再次调用 layoutIfNeeded 来动画到新的状态
        1.  

四,显示

一个视图的显示包含了颜色、文本、图片和 Core Graphics 绘制等视图属性,不包括其本身和子视图的大小和位置。和布局的方法类似,显示也有触发更新的方法,它们由系统在检测到更新时被自动调用,或者我们可以手动调用直接刷新

  1. 自动刷新显示draw rect方法
    1. 对视图内容显示的操作,类似于视图布局的 layoutSubviews ,但是不同于 layoutSubviews,draw 方法不会触发后续对视图的子视图方法的调用。同样,和 layoutSubviews 一样,你不应该直接调用 draw 方法,而应该通过调用触发方法,让系统在 run loop 中的不同结点自动调用
  2. 主动刷新显示setNeedsDisplay()方法
    1. 这个方法类似于布局中的 setNeedsLayout 。它会给有内容更新的视图设置一个内部的标记,但在视图重绘之前就会返回。然后在下一个 update cycle 中,系统会遍历所有已标标记的视图,并调用它们的 draw 方法。如果你只想在下次更新时重绘部分视图,你可以调用 setNeedsDisplay(_:),并把需要重绘的矩形部分传进去(setNeedsDisplayInRect in OC)。大部分时候,在视图中更新任何 UI 组件都会把相应的视图标记为“dirty”,通过设置视图“内部更新标记”,在下一次 update cycle 中就会重绘,而不需要显式的 setNeedsDisplay 调用。然而如果你有一个属性没有绑定到 UI 组件,但需要在每次更新时重绘视图,你可以定义他的 didSet 属性,并且调用 setNeedsDisplay 来触发视图合适的更新。
    2. 视图的显示方法里没有类似布局中的 layoutIfNeeded 这样可以触发立即更新的方法。通常情况下等到下一个更新周期再重新绘制视图也无所谓
      1.  

五,约束

  1. updateConstraints()
    1. 和布局中的 layoutSubviews() 方法或者显示中的 draw 方法类似,updateConstraints() 只应该被重载,绝不要在代码中显式地调用。通常你只应该在 updateConstraints 方法中实现必须要更新的约束
  2. setNeedsUpdateConstraints()
    1. 调用 setNeedsUpdateConstraints() 会保证在下一次更新周期中更新约束。它通过标记“update constraints”来触发 updateConstraints()。这个方法和 setNeedsDisplay() 以及 setNeedsLayout() 方法的工作机制类似
  3. updateConstraintsIfNeeded()
    1. 对于使用自动布局的视图来说,这个方法与 layoutIfNeeded 等价。它会检查 “update constraints”标记(可以被 setNeedsUpdateConstraints 或者 invalidateInstrinsicContentSize方法自动设置)。如果它认为这些约束需要被更新,它会立即触发 updateConstraints() ,而不会等到 run loop 的末尾
  4. invalidateIntrinsicContentSize()
    1. 自动布局中某些视图拥有 intrinsicContentSize 属性,这是视图根据它的内容得到的自然尺寸。一个视图的 intrinsicContentSize 通常由所包含的元素的约束决定,但也可以通过重载提供自定义行为。调用 invalidateIntrinsicContentSize() 会设置一个标记表示这个视图的 intrinsicContentSize 已经过期,需要在下一个布局阶段重新计算
      1.  

六,约束,布局,显示的对比图

屏幕快照 2017-10-16 上午12.43.38.png

七, update cycle 和 event loop 之间的交互

Update Cycle

 

八,动态布局需要考虑的要素

参考:http://www.10tiao.com/html/330/201711/2653579435/2.html

1,运行时变换布局

2,跟踪触摸手势

3,动态字体

4,安全区

5,比例布局

6,stackView

 

九,苹果iOS UI 布局有以下三种主要方法:

Frame layout:直接用代码设置每个控件的 Frame。
使用 auto-resizing masks:可以自动调整子视图与父视图之间的位置关系。
使用 auto-layout。


使用 frame layout 最直接,最灵活。当需要发生变化的时候,所有的改变都有你自己来控制。它带来的问题就是过于繁杂。即使一个很简单的界面,为了适配各种可能的情况,都要花费大量的精力去设计、调试、维持。Frame 的性能高。

使用 auto-resizing masks 可以部分地解决上述问题。但它只是完整的解决方案中的一个子集,无法适应所有可能的情况。而且它只能应对来自外部的改变,如 macOS 中用户调整了窗口大小、iOS中的横屏和分屏。而内部的改变如本地化、app 展示的内容改变这类的问题无法解决。

使用 auto-layout 可以动态地解决内部改变和外部改变。它不直接设置控件的大小和位置,而是通过约束去考虑控件之间的相对关系。功能强大,但可能有点抽象,跟传统的方法不太一致。 AutoLayout 性能低,而且代码冗长蹩脚

十,布局的选择

1,demo级

frame,autoLayout

2,局部级

stactView,UICollectionView

3,页面级

Masonry(基于AutoLayout),MyLayout(基于Frame)

4,性能级

ComponentKit和AsyncDisplayKit(faceBook)

5,跨平台级

flexBox和Yoga

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值