写在前面的话

在iOS应用程序的开发的关于AutoLayout布局的内容一直是一个比较令人头疼的地方...
特别是没有充足的使用经验的时候,各种约束器(Constraint),优先级(Priority),自适应(Self-Sizing)还有控件自身的行为容易把人绕晕~

正巧收藏夹里有一篇岛国作者写的关于多个Label之间相互位置,大小控制的文章,翻译记录下来与各位分享一下。

 

通过AutoLayout掌握固定尺寸

作者:西方
原文链接:https://qiita.com/shtnkgm/items/f0b189e4184fe6c90707

使用固定尺寸

通过AutoLayout来指定View的尺寸的时候,会利用有关宽度与高度的约束条件。
但是,根据内容本身的大小来调整View的尺寸也是可行的。
这个时候使用的是固定尺寸。

什么是固定尺寸

固定尺寸指的是,View的尺寸以它所包含的内容而决定。在英语里,被写作「Intrinsic Content Size」。以UILabel作为举例的话,内容是「Money」的Label,比起内容是「Money Forward」的Label来说,前者的尺寸比较小。

下图是Storyboard上各个Label的固定尺寸的样子。

如果没有设定有关尺寸的约束条件,系统会基于固定尺寸进行布局。

设定关于View的约束条件

结合对画面上配置的两个UILabel的约束条件的设定来进行解说。

设定的是下面四个约束条件:

水平方向

  • 设定Label和Label之间的间距为20
  • 设定左侧的Label与父视图的左侧间距为20
  • 设定右侧的Label与父视图的右侧间距为20以上

垂直方向

  • 设定两个Label在父视图的垂直方向的位置为居中

在这个状态下,来看看在Xcode的预览中各个设备里的排版吧。

没有任何问题的样子。

固定尺寸与其他约束条件的竞争关系

接下来,设定左侧的Label的内容为“Money Money Money Money Money”,右侧的Label的内容为“Forward Forward Forward Forward Forward”。

不仅发生了关于约束条件的错误,在4英寸设备上Forward的Label消失不见了。
(因为具有约束条件竞争关系,实际的表现方式可能具有不同)

错误是,提供了“Compression Resistance Priority”和“Hugging Priority”的两种,请控制优先级的提示。

这是含有固定尺寸的约束条件产生了矛盾,无法正确排列视图的状态。
为了完整地表现各个Label的内容,需要一定的矩形面积,而这超出了尺寸无法将Label放入父视图内,故无法满足其他约束条件。

这样的话,系统无法决定视图的排列。在这里需要设定的是,固定尺寸的优先级。

固定尺寸的优先级

在固定尺寸和其他的约束条件有竞争关系的时候,必须指定哪个值是具有高的优先级。为了那个所使用的是固有尺寸的优先级。

优先级的种类

固有尺寸具有以下两个优先级。

  • Content Compression Registance Priority
    • 内容被折叠的困难度
    • 在内容过大的时候,为了防止内容被折叠,扩大视图的矩形面积
  • Content Hugging Priority
    • 产生余白的困难度
    • 在内容过小的时候,为了防止产生余白,将视图的矩形面积缩小的程度

优先级越高,视图的矩形面积就会更接近它的内容。

在内容过大时候的控制

百闻不如一见。让我们来实际设定一下优先级吧。

现在的问题是,我们的内容太大了。因此,为了解决这个问题,我们需要设定Compression Registance Priority。
把右侧的Label的优先级变高吧(为了防止右侧Label的内容被折叠)。将右侧Label的Compression Registance Priority设定为751。

设定可以在工具区域(Xcode的右边)的Size Inspector中进行(下图)。

在预览中再确认一下,这次左边的Label被完全折叠,无法正常地表示。因为这并不是我们想要的效果,我们设定左边的Label的最小宽度。我们将约束条件设定为最小宽度为65。

再一次确认一下预览,不管在哪个设备下的表示都符合我们的想法了。

在内容过小时候的控制

接下来,将左边的Label的内容改成“M”,右边的Label的内容改成“F”。再一次,出现了关于优先级的错误。
这次由于我们的问题是内容过小,所以我们需要设定的是Content Hugging Priority。

先极力避免左边的Label产生余白(允许右边的Label产生余白)。为此,设定左边的Label的Content Hugging Priority为252。
这里需要注意的是,已经为左边的Label设定了最小宽度为65。这个约束条件的优先级是默认值1000,比Content Hugging Priority的优先级要大,“最小宽度为65”的约束条件是最优先的。

这样的话,不管内容尺寸如何变化,约束条件的矛盾也不会发生了。

使用Label的例子

举例来说,设定左边的Label的内容为“Money Forward”,右边的Label的内容为“お金を前へ。人生をもっと前へ。”,就会变成这个样子。

  • 4英寸
    • 左侧Label的最低宽度为65(Width Priority:最高)
    • 右侧Label的内容尽量多表示(Compression Registance Priority:高)
    • 左侧Label的内容尽量多表示(Compression Registance Priority:低)
  • 4.7英寸
    • 右侧Label的内容全体表示(Compression Registance Priority:高)
    • 左侧Label的内容尽量多表示(Compression Registance Priority:低)
  • 5.5英寸
    • 左侧Label的内容不要余白的情况下表示(Hugging Priority:高)
    • 右侧Label的内容加上余白表示(Hugging Priority:低)

总结

在AutoLayout中,对复数的视图应用固定尺寸的话,无法准确地根据内容的尺寸决定排列布局效果。为了解决这个问题要使用固定尺寸的优先级。

控制固定尺寸的优先级,还有宽度和高度的约束条件,可以实现期望的布局效果。为了控制宽度和高度,不光是固定值,也可以尝试设定最大值或者最小值。

特别的,在Label中表示的内容需要动态变化的话,如果不注意实际场景中的表示,进行测试的话,由于用户环境千差万别,可能会引起无法实现预期效果的问题。

聪明地使用AutoLayout,就算设备尺寸或者内容都变化了,也可以实现正确的布局。