深入剖析AutoLayout 之 何为约束
01 Feb 2015开个坑讲讲Auto Layout的那点事儿. 分卷如下:
- 约束
- 布局空间
- 优先级
- 约束转译
- 布局过程
- 尺寸计算
- 边距
逐卷介绍Auto Layout中的部分概念, 并比对与先前布局机制的异同点.
何为约束
iOS6时, UIKit增加了Auto Layout, 使用约束描述UI对象属性间关系的方式来替代直接设定frame/bounds/center.
NSLayoutConstraint作为约束的载体, 定义了约束相关的属性如下:
- priority 优先级, 取值越高, 优先级越高. 预设的优先级有required/high/low/size fitting四种.
- firstItem 被约束视图
- firstAttribute 被约束属性
- relation 关系, 大于等于/等于/小于等于三种.
- secondItem 参照视图
- secondAttribute 参照属性
- multiplier 倍数因子
- constant 偏移因子
- identifier 标示符
- shouldBeArchived 是否随view一同序列化, 默认NO; 一般而言, 布局约束应序列化, 中间状态不应.
其中的attribute定义如下:
从而, UI对象间的关系可以描述为如下线性关系:
firstItem.firstAttribute >= multiplier × secondItem.secondAttribute + constant 或 firstItem.firstAttribute == multiplier × secondItem.secondAttribute + constant 或 firstItem.firstAttribute <= multiplier × secondItem.secondAttribute + constant
例如:
icon.left == 1 × cell.contentView.left + 10
就表示icon的左侧在cell.contentView左侧+10的位置.
约束的使用限制
- NSLayoutConstraint的属性中priority、constant、identifier和shouldBeArchived外的属性都是readonly的;
- firstItem和firstAttribute不能为空(nil/none), secondItem和secondAttribute则可以;
- 约束必须添加在firstItem和secondItem的共同先祖视图上;
- 约束描述的参照关系不能穿越bounds可以偏移的视图, 如UIScrollView的subview不能设定subview.top == scrollview.superview.top.
使用代码创建约束
NSLayoutConstraint提供了两种构造方法:
###1. +constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
直接使用readonly的属性创建约束. 由于创建时不得不指定所有属性, 即使secondItem不存在、multiplier为1或constant为0也不能避免, 导致可读性和易用性都堪忧, 因而再次推荐笔者的另一篇blog.
###2. constraintsWithVisualFormat:options:metrics:views:
通过Visual Format Language一次创建水平/垂直方向上的一组约束. metrics和views分别为常量和视图映射. Visual Format的具体规则可以参阅Auto Layout Guide, 这里只简单举个例子:
V:|-10-[label(>=70@1000,>=button@250)]-[button][icon]-|
符号 | 含义 |
---|---|
V: | 垂直方向 |
-10-[label] | label与容器上边距为10 |
(>=70@1000,>=button@250) | label高大于等于70, 优先级1000; 高大于等于button高, 优先级250 |
[label]-[button] | label与button间距为默认长度(8) |
[button][icon] | button与icon相邻, 无间距; button和icon使用intrinsic size高 |
[icon]-| | icon与容器下边距为默认长度(8) |
此外, 可以通过options来额外设定Visual Format中视图间的对其关系. options定义如下
Visual Format的强大之处在于它可以清晰的说明一个方向上各视图间的关系, 缺点是:
-
无法使用margin
-
约束设定远离视图创建的位置
使用IB中创建约束
如果使用IB, 在IB中添加约束一般会比代码要便利上许多, IB自带的约束检查器也足够强大. 怎么在IB中添加约束在Raywenderlich或是Cocoachina都能找到一打教程, 就不赘述了. 即使不看教程, 在探究过Auto Layout之后, 把玩两回也不难弄懂要怎么用.
在IB中添加约束也有它的代价:
-
时序限定为创建时
-
整个XIB/storyboard内都必须使用Auto Layout
-
创建大量约束时难以管理
额外提示两点:
-
善用IB右下的工具可以给约束设定工作带来质的飞跃
-
使用拉拽方式设定约束时, 善用shift键也可以一次添加多条约束
-EOF-