博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UIView在AutoLayout下的布局过程
阅读量:2348 次
发布时间:2019-05-10

本文共 3038 字,大约阅读时间需要 10 分钟。

使用 Auto Layout 将 View 显示在屏幕上需要的经过三个步骤。

  1. 更新约束(updateConstraints)
  2. 通过约束关系计算出center和bounds对subviews进行布局(layoutSubViews)
  3. 将布局好的view显示到屏幕(drawRect)

与之相关的方法有如下八个。

  1. setNeedsUpdateConstraints:将 view 标记为需要更新约束,并在稍后触发updateConstraitsIfNeed
  2. updateConstraitsIfNeed:系统会在每个布局节点自动调用此方法。只有约束被标记为需要更新才会调用updateConstraints。此方法可以手动调用。子类不要重写此方法。
  3. updateConstraints:更新约束的实际方法。
  4. setNeedsLayout:将 view 标记为需要更新布局,并在稍后触发layoutIfNeeded。当view的布局改变时会自动调用。
  5. layoutIfNeeded:系统会在每个布局节点自动调用此方法。只有布局被标记为需要更新才会调用layoutSubViews
  6. layoutSubViews:在 iOS5.1 之后的是更新布局的实际方法,之前没有默认实现。只有当 autoresizing 和 constraint 不能满足布局需求时才能重写。不能直接调用。会调用updateConstraintsIfNeeded
  7. setNeedsDisplay:将 view 标记为需要重绘,并在下次绘制循环触发 drawRect。改变布局不会触发此方法。
  8. drawRect:没有默认实现。不能直接调用。

详细

当你使用 Auto Layout 去努力创造你想要的布局时,特别是同时伴随高级使用场景和动画时,放下使用场景,去回想布局过程是怎样工作的,将会带来很大的帮助。

相比使用frame布局,Auto Layout 在 Views 可以被显示之前引入了两个额外的处理工序:更新约束,布局视图 
每一步都依赖前一步;显示依赖布局,布局依赖约束。

第一步:更新约束(updateConstraints)

更新约束可以被认为是一个测量的过程。他从下到上 bottom-up (from subview to super view)去准备在布局时直接设置 views 的 frame 所需要的信息。

你可用setNeedsUpdateConstraints手动触发这个过程。也可以通过对自身约束系统的改变来自动触发这个过程。即便这样,当你在定制 views 中改变可能影响布局的的约束时通知 Auto Layout 也是有必要的。
说到定制的 views,你可以重写updateConstraints以添加你的 view 在这个阶段需要的局部约束。

第二步:布局(Layout)

布局是从上到下 top-down (from super view to subview)进行的。布局的过程事实上是请求约束系统的结果再通过 center 和 bounds 设置给 views。

你可以通过调用setNeedsLayout触发这个过程。setNeedsLayout 实际上并没有在接下来立马请求布局,而是把你的请求记录下来随后刷新。
通过这种方法你不用担心setNeedsLayout调用太频繁,因为所有的布局请求会被合并到一个布局过程。你可以通过调用layoutIfNeeded来立即触发更新视图层的布局过程,如果你下一步操作依赖于视图最新的布局。
在你的定制 view 中你可以通过重写layoutSubviews去获取布局过程的完全控制。我们将在随后展示这样的用法。

第三部:显示(Display)

最后,显示过程将 views 渲染到屏幕,这个过程是独立的,不管你用没用 Auto Layout。

显示过程从上到下 top-down (from super view to subview) 进行,可以用 setNeedsDisplay 触发,并且会整合所有请求延时重绘。在你的定制 views 重写熟悉的drawRect:方法是你获得 views 在显示过程这个阶段的完全控制的途径。
因为每一步都依赖于前一步,所以显示过程将会触发布局过程(如果有任何布局在等待改变)。同样,布局过程将会触发新更新约束过程(如果约束系统有在等到的改变)。
需要记住的是,这三个过程的调用顺序并不是唯一的。
布局(基于约束 Constraint-based 的)是一个重复的过程。在布局过程中基于上一次布局结果改变约束,将会在下一个布局过程后再次触发约束更新。
这将有助于生成 views 高级定制的布局。但是你也有陷入无限循环的风险,如果每个layoutSubviews方法中调用并唤起了另外一个布局过程的话。

总结

  • 如果想要立即改变约束,需要在setNeedsUpdateConstraints后调用updateConstraintsIfNeeded
  • 如果想要立即改变布局,需要在setNeedsLayout后调用layoutIfNeeded

UIConstraintBasedLayoutCoreMethods

 
  1. @interface UIView (UIConstraintBasedLayoutCoreMethods)
  2. - (
    void)updateConstraintsIfNeeded
    NS_AVAILABLE_IOS(
    6_0);
  3. - (
    void)updateConstraints
    NS_AVAILABLE_IOS(
    6_0);
  4. - (
    BOOL)needsUpdateConstraints
    NS_AVAILABLE_IOS(
    6_0);
  5. - (
    void)setNeedsUpdateConstraints
    NS_AVAILABLE_IOS(
    6_0);
  6. @end

setNeedsUpdateConstraints : 当一个自定义的View某一个属性的改变可能影响到界面布局,我们应该调用这个方法来告诉布局系统在未来某个时刻需要更新。系统会调用updateConstraints去更新布局。

updateConstraints :自定义View时,我们应该重写这个方法来设置当前view局部的布局约束。重写这个方法时,一定要调用[super updateConstraints]

needsUpdateConstraints :布局系统使用这个返回值来确定是否调用updateConstraints

updateConstraintsIfNeeded :我们可以调用这个方法触发update Constraints的操作。在needsUpdateConstraints返回YES时,才能成功触发update Constraints的操作。我们不应该重写这个方法。

Auto Layout的布局过程是 update constraints(updateConstraints)-> layout Subviews(layoutSubViews)-> display(drawRect) 这三步不是单向的,如果layout的过程中改变了constrait, 就会触发update constraints,进行新的一轮迭代。我们在实际代码中,应该避免在此造成死循环。

转载地址:http://clxvb.baihongyu.com/

你可能感兴趣的文章
Mac下安装PHP的mcrypt扩展的方法(自己总结的)
查看>>
关于html_entity_decode、空格 以及乱码
查看>>
Box2d no gravity
查看>>
mario collision
查看>>
tiled 地图工具
查看>>
小游戏
查看>>
旋转关节绳子
查看>>
射箭box2d
查看>>
cocos2d iphone-wax cocowax
查看>>
angribird level editor
查看>>
love2d 苹果运行
查看>>
GridBagLayout 的注意
查看>>
ajax 跨域iis6 设置
查看>>
4.0版本改动
查看>>
IE8 9 ajax no-transport ajax 问题
查看>>
oracle 启动dbconsole
查看>>
entity-framework 6解决方案中多个项目使用
查看>>
ios基础
查看>>
unity3d
查看>>
metronic 1.5
查看>>