关键词:
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
-
Content Hugging Priority: 该优先级表示一个控件抗被拉伸的优先级。优先级越高,越不容易被拉伸,默认是251。
-
Content Compression Resistance Priority: 该优先级和上面那个优先级相对应,表示一个控件抗压缩的优先级。优先级越高,越不容易被压缩,默认是750
这些优先级的绝对值意义不大,Autolayout怎么布局只取决于控件优先级的相对值,我们可以把固有内容的两个优先级也看做是约束,那么自动布局将按照一个简单的原则处理所有的约束:优先级高的,先满足(好像是废话,但可以用这个原则去解释Autolayout的行为)
现在还是很模糊,没关系,下面我们将通过实例来看看这条原则是怎么应用的。
实例
我们在View中添加了一个UILabel,并为其添加了三个约束:在竖直方向居中,距离左边屏幕145,距离右边屏幕145。为了看到UILabel的实际宽度,我们将Label的背景色置为灰色。
其运行效果如下:
从最后的显示效果来看,中间的Label被压缩了,来满足左右两个约束。
根据第一个图中标注的优先级,左右约束的优先级比固有内容相关的优先级要高,所以Autolayout布局的时候会优先满足左右两个约束。这时候:左边约束宽度(145) + 右边约束宽度(145) + Label的固有内容宽度 > 屏幕宽度。所以最后只能压缩Label显示的宽度。
Content Compression Resistance Priority
这时候Label是被压缩的,我们就来演示一下Content Compression Resistance Priority这个优先级是如何影响控件的抗压缩特性的
我们修改右边的约束优先级为700
其运行效果如下:
这时候UILabel控件的抗压缩约束优先级比右边约束优先级高,Autolayout先满足左边约束,然后满足UILable控件的固有内容Size的宽度,最后来调整右边约束的宽度。表现出来就是UILable抗压缩特性变强了,它更倾向于显示它固有内容Size。这时候被压缩的就是右边的约束。
Content Hugging Priority
为了演示Label被拉伸的情况,我们将右边的约束优先级恢复为1000,并将左右约束的宽度都改为50。
其运行效果如下:
和压缩的时候类似,左右约束优先级比UILabel的Content Hugging Priority优先级高,并且此时:左边约束宽度(50) + 右边约束宽度(50) + Label的固有内容宽度 < 屏幕宽度。为了满足左右两个约束,就只有拉伸Label。
此时我们将右边约束的优先级变为240。
其运行结果为:
这时候UILabel控件的抗拉伸约束优先级比右边约束优先级高,Autolayout先满足左边约束,然后满足UILable控件的固有内容Size的宽度,最后来调整右边约束的宽度。表现出来就是UILable抗拉伸特性变强了,它更倾向于显示它固有内容Size。这时候被拉伸的就是右边的约束。
实际应用
我们常常遇到的是类似下面的情况:
TitleLabel的显示内容可能会很长,如果不能很好的设置约束就可能覆盖后面显示时间的Label。但显示时间的Label也应该是一个动态的长度。针对这种情况,我们在模拟器中来模拟一下。
两个Label,前面是AddressLabel,后面是TimeLabel,为了不让两个Label覆盖,我们设定前后Label的水平间距>=10,没有调整过任何优先级。
显示效果如下:
这时候系统会默认调整前面Label的宽度,使其压缩,来满足后面Label能够完整显示,这应该是系统默认行为。这样看起来刚刚好,但如果我们的需求是时间在前面,并且需要完全显示。地址信息在后面,如果过长就显示省略号。那么使用上面的默认行为就不能满足要求。
其运行结果为:
这时候前面的TimeLabel会被默认压缩,不能满足要求。这时候我们就可以通过改变控件的抗压缩优先级来满足要求,我们可以把AddressLabel的抗压缩优先级改为740,比TimeLabel默认的750低,那么Autolayout就会去压缩AddressLabel,而使TimeLabel按照它固有内容的宽度显示。这就可以满足我们的要求了。
来看一下最后的显示效果:
More
上面简单阐述了一下相关约束优先级的原理,和他们的简单应用。如果你想去练习一下,我建议你用自动布局去实现一下新浪微博首页的Cell,或者微信朋友圈的Cell。
网友评论
此时我们将左边约束的优先级变为240。
这句话有错误,最后一句应该修改为 ->此时我们将右边约束的优先级变为240。