从OC到Swift

使用 UIStackView 来简化 AutoLayout 布局

2018-06-04  本文已影响0人  智小融

可以维护的 AutoLayout

在使用 AutoLayout 做界面布局的时候,你会发现,做好一个复杂界面的约束并不是一件容易的事,经常需要很多的调试,这在用代码写布局的时候尤为明显,因为没有 IB 给你实时的反馈当前的 Layout 错误。而且不管是在 IB 还是纯代码的 AutoLayout,其可读性都不太好,例如我们创建了下面这样一个 App Store 的界面:

1.png

Label 和 星标图片之间有很多约束,如果我们遇到了需求改动,想要在星标上方多加一行,就得先搞清楚各个约束是干什么的,再打破几个约束,最后增加一个 Label 并且加上约束,费时费力。

iOS 9 发布的时候苹果提供了一个新的AutoLayout 工具 UIStackView,可以自动完成很多类型的布局,并且不用添加任何约束,由 UIStackView 自行管理其 ArrangedSubviews 的约束并且可以让增删变的更简单,大大增加了项目的可维护性,本文就来介绍一下 UIStackView 的使用。

UIStackView 本身是建立在 AutoLayout 的约束之上的,我们不用主动给其子视图添加约束就可以完成自动布局,UIStackView 相当于一个可以为你自动管理内部 View 的一个容器。想要完成布局大多数情况你需要做这三步:

1.调用 -addArrangedSubview: 添加需要布局的 View 到一个 UIStackView 上;
2.配置 UIStackView 的 axix、alignment、distribution、spaciing 这四个属性;
3.如果有必要,再嵌套多个 UIStackView 到一个 UIStackView 中。

UIStackView 的主要方法和属性

2.png
@property(nonatomic) UILayoutConstraintAxis axis;

用于控制 UIStackView 子视图横向或纵向布局,有两种:

3.png
@property(nonatomic) UIStackViewAlignment alignment;

这个属性稍微复杂一点,当 axisHorizontal 时其表示 UIStackView 的子视图相对于其上下边界的对其方式。当 axis 为 Vertical 时,表示 UIStackView 的子视图相对于其左右边界的对其方式,一共有八中,看下面的图示就很好理解了:

4.png 5.png
@property(nonatomic) UIStackViewDistribution distribution;

这个属性用来控制 UIStackView 在其 axis 方向上的分布,分别有如下几种:

6.png

Fill
UIStackView 的子视图会沿着其 axis 填充满 UIStackView,如果子视图在 axis 方向上不能放入 StackViewStackView太小),则会按照子视图的抗压缩优先级属性( Content Compression Resistance Priority)从低到高压缩视图,直到正好填满 StackView 为止。

反之,如果子视图在 axis 方向不能填满 StackViewStackView太大),则会按照子视图的抗拉伸优先级属性(Content Hugging Priority)从低到高拉伸视图,知道正好填满 StackView 为止。

这里说一点,StackView 在没有宽高约束的时候大部分情况是没问题的,因为它会根据子视图的intrinsic content size 、宽高约束、甚至是 frame.size.width frame.size.height 来计算自己的宽高,最终会有一个intrinsic content size,这样我们把 StackView 添加到父视图中的时候,可以不约束其宽高,只定位好 origin 就可以了。

FillEqually
这个属性简单一些,StackView 的子视图会沿着axisStackView 内均匀分布。

FillProportionally
按字面意思解释,和 FillEqually 类似,也是每个子视图都会被等比例拉伸或者压缩,来填满 StackView,但是这个是等比例填满,每个子视图会被 StackView 按照其 intrinsic content size 或者其本身 frame 来进行等比例缩放,如果要拉伸或者压缩,每个子视图都会同时被等比例拉伸或压缩。

EqualSpacing
StackView 会在每个子视图中间留下等相等的空间距,此时 Spacing 属性定义的是这个间距的最小值。如果 StackView 足够大,可以保持子视图的原始尺寸,不拉伸,但是如果 StackView 太小,子视图会被压缩,也是按照子视图的抗压缩优先级属性( Content Compression Resistance Priority)从低到高压缩,此时如果有两个子视图有相等的抗压缩优先级,StackView 就不知道压缩哪个了,需要调整子视图的优先级,不要出现相等的情况。

EqualCentering
StackView 会把每个子视图按照中心点等距离排列,此时 Spacing 属性定义的是这个间距的最小值。如果 StackView 足够大,可以保持子视图的原始尺寸,不拉伸,但是如果 StackView 太小,子视图会被压缩,也是按照子视图的抗压缩优先级属性( Content Compression Resistance Priority)从低到高压缩,此时如果有两个子视图有相等的抗压缩优先级,StackView 就不知道压缩哪个了,需要调整子视图的优先级,不要出现相等的情况。

@property(nonatomic) UIStackViewAlignment alignment;

按照 distribution 属性中的布局方式控制子视图之间的间距。

总结

在本文结束之前,我们看一下上面的 AppStore Demo 在使用 UIStackView 布局后的情况,是不是简介清爽了许多。

7.png

最后,引用一下 WWDC 苹果工程师的话,如果你使用 AutoLayout,那么请 Start With Stack View, use constraints as needed!

上一篇下一篇

猜你喜欢

热点阅读