美文网首页常看iOS工作系列iOS实战
Autolayout中关于intrinsic content、相

Autolayout中关于intrinsic content、相

作者: dev_xdyang | 来源:发表于2015-08-12 16:47 被阅读6083次
    关键词:   
    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。

    相关文章

      网友评论

      • ForestSen:好东西 支持了
      • Cocos543:和压缩的时候类似,左右约束优先级比UILabel的Content Hugging Priority优先级高,并且此时:左边约束宽度(50) + 右边约束宽度(50) + Label的固有内容宽度 < 屏幕宽度。为了满足左右两个约束,就只有拉伸Label。
        此时我们将左边约束的优先级变为240。
        这句话有错误,最后一句应该修改为 ->此时我们将右边约束的优先级变为240。
        dev_xdyang:@ded8212b3bf0 感谢指出,确实有问题,已经修改。谢谢!
      • 497364cad8e5:Mark,优先级方面讲解到位!

      本文标题:Autolayout中关于intrinsic content、相

      本文链接:https://www.haomeiwen.com/subject/pvwiqttx.html