First we will recap the steps it takes to bring views on screen with Auto Layout enabled. When you’re struggling to produce the kind of layout you want with Auto Layout, specifically with advanced use cases and animation, it helps to take a step back and to recall how the layout process works.

Compared to working with springs and struts, Auto Layout introduces two additional steps to the process before views can be displayed: updating constraints and laying out views. Each step is dependent on the one before; display depends on layout, and layout depends on updating constraints.

The first step – updating constraints – can be considered a “measurement pass.” It happens bottom-up (from subview to super view) and prepares the information needed for the layout pass to actually set the views’ frame. You can trigger this pass by calling setNeedsUpdateConstraints. Any changes you make to the system of constraints itself will automatically trigger this. However, it is useful to notify Auto Layout about changes in custom views that could affect the layout. Speaking of custom views, you can override updateConstraints to add the local constraints needed for your view in this phase.

The second step – layout – happens top-down (from super view to subview). This layout pass actually applies the solution of the constraint system to the views by setting their frames (on OS X) or their center and bounds (on iOS). You can trigger this pass by calling setNeedsLayout, which does not actually go ahead and apply the layout immediately, but takes note of your request for later. This way you don’t have to worry about calling it too often, since all the layout requests will be coalesced into one layout pass.

To force the system to update the layout of a view tree immediately, you can call layoutIfNeeded/layoutSubtreeIfNeeded (on iOS and OS X respectively). This can be helpful if your next steps rely on the views’ frame being up to date. In your custom views you can override layoutSubviews/layout to gain full control over the layout pass. We will show use cases for this later on.

Finally, the display pass renders the views to screen and is independent of whether you’re using Auto Layout or not. It operates top-down and can be triggered by calling setNeedsDisplay, which results in a deferred redraw coalescing all those calls. Overriding the familiar drawRect: is how you gain full control over this stage of the display process in your custom views.

Since each step depends on the one before it, the display pass will trigger a layout pass if any layout changes are pending. Similarly, the layout pass will trigger updating the constraints if the constraint system has pending changes.

It’s important to remember that these three steps are not a one-way street. Constraint-based layout is an iterative process. The layout pass can make changes to the constraints based on the previous layout solution, which again triggers updating the constraints following another layout pass. This can be leveraged to create advanced layouts of custom views, but you can also get stuck in an infinite loop if every call of your custom implementation of layoutSubviews results in another layout pass.

  • setNeedsUpdateConstraints makes sure a future call to updateConstraintsIfNeeded calls updateConstraints.
  • setNeedsLayout makes sure a future call to layoutIfNeeded calls layout(在iOS上是 layoutSubviews).

如果我们实现一个Custom View,并且这个Custom view会在加载nib后需要更新一个constraints(添加或者删除),那这个CustomView 应该 overrid updateConstraints方法,在这个方法中,将需要update 的constraints设置完成后,调用setNeedsUpdateConstraints: (?在哪里调用呢?),通知下次的  measurement pass时custom view 的updateConstraints会被调用到。

如果你的Custom View需要自定义的layout行为时,你才需要override layout方法(在iOS上是layoutSubViews),并且调用setNeedsLayout: 方法通知Layout pass能调用到custom view 的layout方法。如果不override layout方法,那几乎没有任何需要调用setNeedsLayout:,因为如果constaint有任何变化,layout pass会调用updateConstraintsIfNeeded并完成constraint 的更新,然后根据constraint的变化进行layout。所以说,底层的变化会被监测到,本层又没有什么特殊,那就没必要使用setNeedsLayout:。

如果你的代码需要对于constraint的更新立刻反应到constraint上,那你应该调用updateConstraintsIfNeeded,如果需要立刻反应到layout上,那应该调layoutIfNeeded,如果希望立刻反应到Display上,应该调用啥呢?事实上,这是不允许的,所有的draw必须遵照cycle来,调用setNeedsDisplay可以让这个view在下一个draw cycle时被redraw,但是没有API可以让draw立刻发生。

Reference:

1. http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

2. https://developer.apple.com/library/mac/releasenotes/UserExperience/RNAutomaticLayout/

最新文章

  1. Android 底部弹出Dialog(横向满屏)
  2. C#SerialPort如何读取串口数据并显示在TextBox上
  3. spring官网下载
  4. ASP.Net一键自动化更新代码、编译、合并dll、压缩js、css、混淆dll、zip打包、发布到测试环境的bat批处理
  5. 空的安卓工程添加activity
  6. 用c#开发微信 (19) 公众平台接口权限列表说明 - 订阅号、服务号认证后的区别
  7. 如何将list转为json?
  8. java课堂动手动脑博客
  9. Windows下Wamp装不上Memcache扩展
  10. Powershell profile.ps1 cannot be loaded because its operation is blocked by software restriction policies
  11. python-登录-注册-修改密码
  12. php封装redis负载均衡类
  13. Spring Boot——开发新一代Spring应用
  14. C# 双引号的输出
  15. java_JDBC(3)
  16. 手机自动化测试:appium源码分析之bootstrap十六
  17. init启动进程
  18. Java第五周学习总结
  19. pc端移动端拖拽实现
  20. node.js学习4--------------------- 根据不同路径来响应内容,以及中文乱码的解决

热门文章

  1. sublime设置备份
  2. android项目的结构和布局
  3. AOJ 0121: Seven Puzzle (BFS DP STL 逆向推理)(转载)
  4. spark统计
  5. sourceforge免费空间申请及使用笔记
  6. jquery总结05-常用事件02-表单事件
  7. Java中ExecutorService和CompletionService区别
  8. 01-C语言概述
  9. jQuery Easing 使用方法及其图解
  10. Codeforces Round #263 (Div. 1)