iOS AutoLayout还可以这样玩

网上关于Auto Layout
的文章繁多, 但是总觉得有些内容并没有说清楚。所以在这篇博文,我将通过一个demo演示Auto Layout
中几个容易被忽略,但是又相当重要的概念
demo效果

demo 中要通过约束要实现的效果如下:
- backgroundView width>=60;
- backgroundView的width随着Label中内容的增加而增加
- backgroundView与其superView的margin>=30。也就是当Label的内容过长时,会显示出省略号。
概念
要实现demo 中的效果前,需要知道下面的几个概念:
1, Constraint equalities
(暂且叫做约束等式):这个就是常见的约束类型。不再赘述,举几个例子:
Red.top = 1.0 * Superview.top + 20.0 Superview.bottom = 1.0 * Red.bottom + 20.0 Red.top = 1.0 * Blue.top + 0.0 Red.bottom = 1.0 * Blue.bottom + 0.0
2, Constraint Inequalities
(暂且叫做约束不等式):它指定一个区域而不是一个确切的值。
// Setting the minimum width View.width >= 0.0 * NotAnAttribute + 40.0 // Setting the maximum width View.width <= 0.0 * NotAnAttribute + 280.0
3,Constraint Priorities
约束优先级 : 约束优级是一个0-1000的数值。当两个约束出现冲突时,优先级高的约束将保留,优先级低的约束失效。
4,Intrinsic Content Size
内在内容size: 有些view 可以根据其内容设定其size。比如说UILabel,UIButton等,他们的size刚好能够容纳其内容支持Intrinsic Content Size
的view如下:

5, content-hugging priorities
抗拉伸优先级(默认250) :这个优先级与 Intrinsic Content Size
相关。假如一个Label的Intrinsic Content Size
width=50, 现在添加一个width=60的约束(默认优先级是1000)现在Label就会拉伸 。如果将 约束width=60的优先级设置成小于250的值,Label就不会被拉伸。
6, compression-resistance priorities
抗压缩优先级(默认750):这个优先级也与 Intrinsic Content Size
相关。假如一个Label的Intrinsic Content Size
width=50, 现在添加一个width=40的约束(默认优先级是1000)现在Label就会压缩 。如果将 约束width=40的优先级设置成小于750的值,Label就不会被压缩。 可以看出 content-hugging priorities
和compression-resistance priorities
用于抵抗其他约束对viewIntrinsic Content Size
的改变。
###实战介绍完上面的概念,让我们使用他们完成上面demo效果。
1, 新建工程,打开storyboard。添加backgroundView(继承自UIView), 设置背景颜色为灰色并添加 水平居中和垂直居中约束。此时会出现约束错误,这是因为这个backgroundView只设置了position,没有设置size。 不必担心,一会就可解决这个问题;
约束如下:


view层级关系如下:

添加下列约束:


此时的约束没有任何错误了显示效果如下:

3, 此时通过给Label添加文字,backgroundView也会相应增大(只分析水平方向)。为什么增大? 这是因为Label的text决定Intrinsic Content Size
的大小, text增多,Intrinsic Content Size
相应增加。Label与backgroundView 的margin为10。所以根据这一系列的关系导致了 给Label添加文字,backgroundView也会相应增大。

4, 现在有个问题, 当label中的文字太多时,backgroundView的宽度会超出其父view范围,这显然不太好。添加一个约束使backgroundView与其父view之间有一个最小的margin。 这时就要使用约束不等式了。约束不等式可以指定一个范围而不是一个确切的数值。看下面的例子。

添加如下约束, 这样backgroundView和superView 之间的margin最小是30。当label中的内容过长时,内容就会被压缩。But Why?


5 , backgroundView 的width随Label中内容的增加而增加。 当backgroundView 与其superView 的margin=30后,再增加 backgroundView 的width就会产生约束冲突了(与之前设置的 ‘backgroundView和superView 之间的margin最小是30’ 这条约束产生冲突 )。那么stroyboard是如何解决冲突的那? 对,就是优先级。‘backgroundView和superView 之间的margin最小是30’这条约束的优先级时1000, 是最大优先级。 Label 的抗压缩优先级默认750,1000>750, Label这能被压缩了(内容省略了一部分)。如果你将这两个优先级大小交换一下,backgroundView与superView 就之间不会出现margin了。
6, 当label中有一个字母是, 效果是这样的。 好丑。。。。

我们给backgroundView设置一个最小width约束。 我们设置backgroundView的width =60约束, 并设置优先级996。(当然,你也可以使用width >=60这样的约束。这里为了演示优先级)现在的效果是这个样子的:

又出问题了。。。 虽然backgroundView width=60确实起作用了,但是Label内容增加时backgroundView的width并没有增加。这还是优先级的问题。Label 的抗压缩优先级是750, backgroundView width=60的优先级时996,996>750, 当然会出问题了。 现在只需让 Label的抗压缩优先级大于backgroundView width=60的优先级就可以了 。
7, 关于抗拉伸优先级,没想到很好的例子,就不演示了。
结语
一种布局效果能通过多种约束方式实现出来,关键是思路清晰,一步一步的来。参考资料,当然是 官网了。希望对你有帮助,如有帮助就给个喜欢吧。