Autolayout中关于intrinsic content、相关优先级及其应用
关键词:
intrinsic content size(固有内容大小)、约束优先级、
Content Hugging Priority、
Content Compression Resistance Priority
理论
-
intrinsic content size: 有些控件能通过自己显示的内容计算出需要的Size,这个自动计算出来size就叫该控件的固有内容大小。这个大小是和需要显示的内容相关的。UIButton,UILabel就是具有固有内容大小属性的控件。UIButton可以根据它的title字符串长度和需要显示的image来计算需要的Size,UILabel可以根据它的text来计算。
-
约束优先级: 在Autolayout中每个约束都有一个优先级,在xib或storyboard中双击一个约束即可看到它的优先级。优先级的范围是1 ~ 1000。创建一个约束,默认的优先级是最高的1000
![](https://i-blog.csdnimg.cn/blog_migrate/dadf93681504274cc9070a5d33f5ea28.webp?x-image-process=image/format,png)
-
Content Hugging Priority: 该优先级表示一个控件抗被拉伸的优先级。优先级越高,越不容易被拉伸,默认是251。
-
Content Compression Resistance Priority: 该优先级和上面那个优先级相对应,表示一个控件抗压缩的优先级。优先级越高,越不容易被压缩,默认是750
这些优先级的绝对值意义不大,Autolayout怎么布局只取决于控件优先级的相对值,我们可以把固有内容的两个优先级也看做是约束,那么自动布局将按照一个简单的原则处理所有的约束:优先级高的,先满足(好像是废话,但可以用这个原则去解释Autolayout的行为)
现在还是很模糊,没关系,下面我们将通过实例来看看这条原则是怎么应用的。
实例
我们在View中添加了一个UILabel,并为其添加了三个约束:在竖直方向居中,距离左边屏幕145,距离右边屏幕145。为了看到UILabel的实际宽度,我们将Label的背景色置为灰色。
![](https://i-blog.csdnimg.cn/blog_migrate/db67625f045d31834765eee9da7e8948.webp?x-image-process=image/format,png)
其运行效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/d2e7ba9ce2669fbb934e1072d6f64c75.webp?x-image-process=image/format,png)
从最后的显示效果来看,中间的Label被压缩了,来满足左右两个约束。
根据第一个图中标注的优先级,左右约束的优先级比固有内容相关的优先级要高,所以Autolayout布局的时候会优先满足左右两个约束。这时候:左边约束宽度(145) + 右边约束宽度(145) + Label的固有内容宽度 > 屏幕宽度。所以最后只能压缩Label显示的宽度。
Content Compression Resistance Priority
这时候Label是被压缩的,我们就来演示一下Content Compression Resistance Priority这个优先级是如何影响控件的抗压缩特性的
我们修改右边的约束优先级为700
![](https://i-blog.csdnimg.cn/blog_migrate/fc2d07e27d540e9b4f3f3c744d36ef66.webp?x-image-process=image/format,png)
其运行效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8767a7e9b4903b3f2862dfbd7d345a5a.webp?x-image-process=image/format,png)
这时候UILabel控件的抗压缩约束优先级比右边约束优先级高,Autolayout先满足左边约束,然后满足UILable控件的固有内容Size的宽度,最后来调整右边约束的宽度。表现出来就是UILable抗压缩特性变强了,它更倾向于显示它固有内容Size。这时候被压缩的就是右边的约束。
Content Hugging Priority
为了演示Label被拉伸的情况,我们将右边的约束优先级恢复为1000,并将左右约束的宽度都改为50。
其运行效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/dc8446c7e6ea0a932ecabbeb3b620c78.webp?x-image-process=image/format,png)
和压缩的时候类似,左右约束优先级比UILabel的Content Hugging Priority优先级高,并且此时:左边约束宽度(50) + 右边约束宽度(50) + Label的固有内容宽度 < 屏幕宽度。为了满足左右两个约束,就只有拉伸Label。
此时我们将右边约束的优先级变为240。
其运行结果为:
![](https://i-blog.csdnimg.cn/blog_migrate/a02b484e86b22b53944ab5cac8aba1ae.webp?x-image-process=image/format,png)
这时候UILabel控件的抗拉伸约束优先级比右边约束优先级高,Autolayout先满足左边约束,然后满足UILable控件的固有内容Size的宽度,最后来调整右边约束的宽度。表现出来就是UILable抗拉伸特性变强了,它更倾向于显示它固有内容Size。这时候被拉伸的就是右边的约束。
实际应用
我们常常遇到的是类似下面的情况:
![](https://i-blog.csdnimg.cn/blog_migrate/bbf5f4dc0bb201b15f69b4442b4442ae.webp?x-image-process=image/format,png)
TitleLabel的显示内容可能会很长,如果不能很好的设置约束就可能覆盖后面显示时间的Label。但显示时间的Label也应该是一个动态的长度。针对这种情况,我们在模拟器中来模拟一下。
![](https://i-blog.csdnimg.cn/blog_migrate/a2beb38abbba2f9a8771c1bb36677cf3.webp?x-image-process=image/format,png)
两个Label,前面是AddressLabel,后面是TimeLabel,为了不让两个Label覆盖,我们设定前后Label的水平间距>=10,没有调整过任何优先级。
显示效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/e2b7c9c3ed44796795ae06ce814f5445.webp?x-image-process=image/format,png)
这时候系统会默认调整前面Label的宽度,使其压缩,来满足后面Label能够完整显示,这应该是系统默认行为。这样看起来刚刚好,但如果我们的需求是时间在前面,并且需要完全显示。地址信息在后面,如果过长就显示省略号。那么使用上面的默认行为就不能满足要求。
其运行结果为:
![](https://i-blog.csdnimg.cn/blog_migrate/1d48851b12d528ec66e9517b6d25f41f.webp?x-image-process=image/format,png)
这时候前面的TimeLabel会被默认压缩,不能满足要求。这时候我们就可以通过改变控件的抗压缩优先级来满足要求,我们可以把AddressLabel的抗压缩优先级改为740,比TimeLabel默认的750低,那么Autolayout就会去压缩AddressLabel,而使TimeLabel按照它固有内容的宽度显示。这就可以满足我们的要求了。
来看一下最后的显示效果:
![](https://i-blog.csdnimg.cn/blog_migrate/6a5109f8852db19a96ca7a20e85e53d3.webp?x-image-process=image/format,png)