[Android开发学iOS系列] Auto Layout

[Android开发学iOS系列] Auto Layout内容:

  • 介绍什么是Auto Layout.
  • 基本使用方法
    • 在代码中写约束的方法
  • Auto Layout的原理
  • 尺寸和优先级
  • Auto Layout的使用细则
    • 重要的属性
    • StackView
    • Layout Guide
  • Performance
  • Debugging
What is Auto LayoutAuto Layout会根据constraints(约束)动态计算出view hierarchy中所有View的位置和大小.
对于Android开发者来说, Auto Layout很容易上手, 它非常像ConstraintLayoutRelativeLayout: 给View规定它上下左右和谁对齐, 决定UI的位置和大小.
Auto Layout的约束更宽泛一些, 不仅仅是两个View之间的关系, 还有宽高, 比率等设置, 并且可以有一些大于小于等的范围设置.
Auto Layout不是一个View开始学Auto Layout我还以为它是一个叫AutoLayout的View, 把其他子View包进去然后设置一些放置规则, 就类似于Android的ConstraintLayout或者RelativeLayout.
但是其实不是, AutoLayout不是一个具体的View, 它代表的是一种计算引擎. 因为在代码里你从来不需要写AutoLayout这个关键字, 写的从来都是Constraints.
开发者为View设置足够多的约束, 规定和这个View位置和大小相关的因素, 这个引擎就可以为我们计算出View的位置和大小.
AutoLayout为了解决什么问题不同屏幕适配; 可以合理应对变化的responsive UI.
改变布局有内外两种因素, 除了屏幕尺寸, 屏幕旋转, 窗口大小改变等外部因素.
内部因素还包含了内容的动态变化, 国际化的支持, 字体的调整等.
和Auto Layout平行的解决方案是什么摆放UI有三种主要的方法:
  • 在程序里给每个View设置frame.
  • 设置frame, 结合使用autoresizing masks来应对外部变化. (autoresizing mask定义了一个view的frame在它的superview frame变化时应该如何变化.)
  • 使用Auto Layout.
可以看出第二种只是在基于frame的方式上做出了一点改进, 所能应对的也仅仅是外部变化, 有一定的局限性. 所以可以把前两种归类为一种.
这也正是Auto Layout出现之前的解决方案, 即基于frame的布局方式.
Auto Layout的思考点不再着眼于view frame, 而是view的relationship.
如何使用Auto Layout写iOS的UI有多种方式, Auto Layout属于UIKit, 在写的时候, 可以用storyboard, 也可以直接在代码中写约束.
在storyboard里面有一些好处, 比如所见即所得, 而且ide会给出一些warnings, 比如控件在storyboard上的位置与约束不一致, 会提示, 并且可以选择方式修复.在storyboard里面写约束确实是不容易出错的一种方式, xcode的操作也很直观, 这里不做演示了.
【[Android开发学iOS系列] Auto Layout】之前我们也讨论过, 用storyboard写UI存在阅读性差, 代码版本管理和团队合作都有问题等.所以具体使用需要看实际情况.
关于约束, location和size的约束不能混着用, 这个也是从逻辑上就可以理解的.比如让某个view的top和parent的top对齐(或者再offset个常量)是可以的, 但是让top等于某个size就不能理解了.
在代码中创建约束如果不用Interface Builder, 而是选择在代码中创建约束, 那么仍然有多种选择:
  • 使用layout anchor.
  • 使用NSLayoutConstraint类.
  • 使用Visual Format Language.
我们在改变约束的时候通常不会add/remove constraints, 而是active/deactivate.
使用Layout anchor这个方法可能是最直观的一种方法.
// Get the superview's layoutlet margins = view.layoutMarginsGuide// Pin the leading edge of myView to the margin's leading edgemyView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true// Pin the trailing edge of myView to the margin's trailing edgemyView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true// Give myView a 1:2 aspect ratiomyView.heightAnchor.constraint(equalTo: myView.widthAnchor, multiplier: 2.0).isActive = true

经验总结扩展阅读