UIStackView简介
UIStackView
是iOS 9+支持的布局控件,主要用于线性布局,可以简化布局,减少约束的使用。之前学过些WPF,它也有一个类似的布局控件。不得不说用起来确实很方便。
应用场景
主要用于线性布局,支持横向和纵向
主要属性
-
axis
属性决定布局方向,水平或垂直; -
distribution
设置布局方向的布局方式; -
alignment
设置垂直于布局方向的方向的布局方式; -
spacing
,使用该属性可以设置子视图的最小间距; -
isBaselineRelativeArrangement
,该属性决定了垂直方向的视图间距是否从基准线开始计算; -
isLayoutMarginsRelativeArrangement
,该属性决定了子视图的布局是否相对于他的 layout margins。
本文没有涉及最后两个属性。
为什么要使用UIStackView
UIStackView
可以在一定程度上减少约束,简化布局,并且使用灵活。在下一节,我将用两种布局思路实现一个简单的登录界面。
使用UIStackView需要注意的地方
-
UIStackView
本身是基于Auto Layout实现的,也就是说它会自动帮你生成一些约束。因此,当你给子视图添加约束时,注意不要跟这些隐含的约束冲突。 - 在处理含有
intrinsicContentSize
属性控件的时候,注意Content Hugging和Content Compression Resistance约束的优先级,否则会造成拉伸错误。 -
UIStackView
没有intrinsicContentSize
属性。
使用UIStackView实现简单的登录界面
这一节,我将使用两种思路实现一个简单的登录界面。思路一参照 Auto Layout Guide,将一个UILabel
和一个UITextField
放入到同一个UIStackView中,也就是有几行就会有几个UIStackView
我称之为以行为主。思路二,将所有的UILabel
放入到一个UIStackView
中,将所有的UITextField
放入到一个UIStackView
中,也就是有几列数据就会有几个UIStackView
,我称之为以列为主。
思路一:以行为主
这种思路参照了Auto Layout Guide,比较容易想到。每当需要添加一行时,添加一个UIStackView
就好了,如下图所示:

图中,
- 白色的矩形框表示
UIStackView
- 粉色的矩形框表示
UILabel
- 绿色的矩形框表示
UITextField
需要的约束有:
- 对于最外层的
UIStackView
,为垂直方向布局:
- leading等于父视图的leadingMargin
- trailing等于父视图的trailingMargin
- top等于topLayoutGuide的bottom
- 对于所有的
UILabel
- Content Hugging的优先级为251
- 对于所有的
UITextField
- Content Hugging的优先级为250
- width相等
思路二:以列为主
这种思路以列为先,有几列数据就设置几个UIStackView
。

需要的约束有:
- 对于最外层的
UIStackView
,为垂直方向布局:
- leading等于父视图的leadingMargin
- trailing等于父视图的trailingMargin
- top等于topLayoutGuide的bottom
- 对于所有的
UILabel
- Content Hugging的优先级为251
- 对于所有的
UITextField
- Content Hugging的优先级为250
- 对于所有的子
UIStackView
- 高度相等
另外,需要注意的是,为了使UILabel
和UITextField
更好地对齐,需要设置UILabel
所在的UIStackView
的Distribution
为 * Fill Equally*。
对比
上述两种思路均可以达到目的,复杂性也比较类似。但是就灵活性而言,思路二更好一些。每当需要添加或删除一行时,思路一可能需要重新设置宽度约束,而思路二不需要调整约束。但是,Content Hugging的优先级二者都需要考虑。
讨论
苹果引入UIStackView
的初衷是为了降低布局的复杂度,并建议优先采用它解决布局问题。从本文可以看出,UIStackView
的使用比较简单,可以手动额外添加所需的约束,比较灵活。此外,本文中还有其他一些UIStackView
特性没涉及到,比如说动态添加元素等,你可以参考下官方的文档。项目示例代码见GitHub
网友评论