UIStackView-入门

1.前言

UIStackView是Apple在iOS9推出的轻量控件,但一直没尝试使用,页面布局还是停留在UITableView与UICollectionView。虽然这两个控件可以满足大部分界面,但是对于复杂的界面,所带来的约束也会变多变复杂。所以针对这种场景,UIStackView应运而生。

2.知识背景

熟悉AutoLayout的同学会了解以下两个属性,由于UIStackView会受这两个属性影响整体布局,所以建议不熟悉的可以先温故。

  • Content Hugging Priority
    • 内容抗拉伸优先级,数字越大抗拉伸能力越强。
  • Content Compression Resistance Priority
    • 内容抗压缩优先级,数字越大抗压缩能力越强。

3.基础属性

UIStackView 有几个重要的属性来控制整体布局,有点像前端的Flex布局。

3.0 UIStackView布局

以下文章所描述的UIStackView是基于以下布局所建立的,里面所包含的是四个Label。

1
Top:0,Tralling:0,Height:100,Leading:0

3.1 Spacing

控制控件内元素之间间隔的大小

3.2 Axis

控制控件所有元素整体排列方向

  • Horizontal
    • 水平方向(默认)

  • Vertical
    • 垂直方向

3.3 Distribution

Axis平行方向的整体元素排列布局配置属性。

3.3.1 Fill

关于设置Fill的效果,对于不同元素的内容大小与优先级属性,会有所区别。

  • Fill
    • 填充(默认)

所有元素属性优先级相同,并且字体内容相同。

现象:系统布局并不知道怎么填充,所以会报建议设置不同元素的优先级属性去解决布局问题。

所有元素属性优先级相同,但字体内容不相同。

1
2
//标签内容
测试测试测试测试测试、测试测试测试、测试测试、测试

现象:全部标签在一个屏幕下不能将内容全部展示的时候,会有标签被压缩掉,但是对于四个标签,优先级属性是一样的。

结论:从图片可以看出,在相同优先级下,Fill布局是先计算出元素固有宽度,然后如果需要压缩,则按照顺序压缩,越排在后面的元素越容易被压缩。

所有元素属性优先级不相同,并且字体内容也不相同。

1
2
//标签内容
测试测试测试测试测试、测试测试测试、测试测试、测试

将最后一个标签的抗压缩水平属性调高为751,其余三个还是750

现象:可以看到第四个没有被压缩,而是第三个被压缩了。

结论:从图片可以看出,在不相同优先级下,Fill布局是先计算出元素固有宽度,然后如果需要压缩,再根据不同优先级属性确定哪个元素先不被压缩,然后再往前找到可以压缩的元素,进行压缩。

3.3.2 Fill Equally
  • Fill Equally
    • 根据UIStackView所拥有的的宽/高进行等分布局
1
2
//标签内容
测试测试测试测试测试、测试测试测试、测试测试、测试

现象:可以看到四个标签所有拥有的宽度都是相等的,。

结论:从图片可以看出,设置Fill Equally后,布局与元素的内容大小、优先级属性没有任何关联。

3.3.3 Fill Proportionally
  • Fill Proportionally
    • 根据元素内容所占比例进行布局
1
2
//标签内容
测试测试测试测试测试、测试测试测试、测试测试、测试

现象:可以看到四个标签所拥有的宽度是按照内容大小进行分割的。

结论:从图片可以看出,设置Fill Proportionally后,布局只与元素内容大小有关联,与优先级属性没有关联。

3.3.4 Equal Spacing
  • Equal Spacing
    • 根据所有元素间隔相等方式布局

结论:设置Equal Spacing与设置Fill差不多,布局先计算出元素固有宽度,并算出大于或等于控件原本设置间隔的相同间隔,然后如果需要压缩,再根据不同优先级属性确定哪个元素先不被压缩,然后再往前找可以压缩的元素进行压缩。具体可以参考以下测试。

以下测试UIStackView Spacing设置为2。

所有元素属性优先级相同,并且字体内容相同。

1
2
//标签内容
测试测试、测试测试、测试测试、测试测试

现象:可以看到四个元素之间的间隔是相等的。

所有元素属性优先级相同,并且字体内容不相同。

1
2
//标签内容
测试测试测试测试、测试测试、测试测试、测试测试

现象:可以看到内容过长后同样也会出现设置Fill一样的的问题,不够显示的话会被压缩。虽然优先级属性一样,但还是选择压缩最后一个元素,然后还会保留控件原本设置Spacing为2的间隔,因为这是最小间隔

所有元素属性优先级不相同,并且字体内容不相同。

1
2
//标签内容
测试测试测试测试、测试测试、测试测试、测试测试

将最后一个标签的抗压缩水平属性调高为751,其余三个还是750

3.3.5 Equal Centering
  • Equal Centering
    • 所有元素中点间的距离相等方式布局

结论:设置Equal Centering与设置Fill差不多,布局先计算出元素固有宽度,然后计算不同元素中心点的间隔。然后如果需要压缩,再根据不同优先级属性确定哪个元素先不被压缩,然后再往前找可以压缩的元素进行压缩。

但是我发现如果个数太少或者某些元素中心点距离比较极端是不能达到等中心间距的效果,因此如果要使用此方式,则需要考虑兼容情况比较多。具体可以参考以下测试。

以下测试UIStackView Spacing设置为2。

元素个数比较少,并且字体内容相同。

现象:元素中心点距离是一样的

元素个数比较多,并且字体内容相同。

1
2
//标签内容
6个测试测试

现象:通过被压缩方式达到元素中心距离是一样的

元素个数比较少,元素宽度极端。

1
2
//标签内容
测试测试测试测试测试测试、测试、测

现象:由于个数比较少,并且第一元素宽度算是比较大,导致每两个元素间的中心间距达不到相等的效果。

元素个数比较少,元素宽度极端。

1
2
//标签内容
测试测试测试测试测试测试测试测试测试测试测试测试、测试、测试测试测试测试测试

现象:屏幕不能全展示情况下,虽然达到了全部元素中心间距离相等,但是第二个元素被压缩。

3.4 Alignment

Axis垂直方向的整体元素排列布局配置属性,在Axis的值不同时会有不同的名称。

3.4.1 Fill
  • Fill
    • 填充(默认)

3.2 Axis展现效果一样,则不重复图片。

3.4.2 Top/Leading
  • Top/Leading
    • 对应顶部方向对齐

Horizontal

现象:全部元素顶部对齐。

Vertical

现象:全部元素向左对齐。

3.4.3 Center
  • Center
    • 对应居中方向对齐

Horizontal

现象:全部元素垂直居中对齐。

Vertical

现象:全部元素水平居中对齐。

3.4.4 Bottom/Trailling
  • Bottom/Trailling
    • 对应底部方向对齐

Horizontal

现象:全部元素底部对齐。

Vertical

现象:全部元素向右对齐。

3.4.5 First BaseLine
  • First BaseLine
    • 仅限在Horizontal使用,按照元素首行基线对齐

Horizontal

现象:在垂直方向上,先确定全部元素首行基线作为起点,再向下确定整体元素布局终点。

3.4.5 Last BaseLine
  • Last BaseLine
    • 仅限在Horizontal使用,按照元素末行基线对齐

Horizontal

现象:在垂直方向上,先确定全部元素末行基线作为起点,再向上确定整体元素布局终点。