注:本文节选并翻译自Stack Views
嵌套的多个Stack View
以下做法展示了一个使用多层嵌套stack view组成的复杂布局。但是,此例中,stack view无法单独生成所有的约束。因此,我们额外需要提供更加完整的约束。
在视图层次完成之后,添加约束展示在下一章节,视图和约束。
视图和约束
在使用多个嵌套的stack view时,最容易的使用方式就是“从内到外”。首先,在Interface Builder中布局出名称行。把label和text field放到相对正确的位置上,同时选中,然后依次点击Editor > Embed in > Stack View菜单项。这便创建了一个水平stack view。
下一步,把这些对象水平放好,全选,再次点击Editor > Embed in > Stack View菜单项。这便创建了一个多行的水平stack view。如下图所示,继续创建界面。
- Root Stack View.Leading = Superview.LeadingMargin
- Root Stack View.Trailing = Superview.TrailingMargin
- Root Stack View.Top = Top Layout Guide.Bottom + 20.0
- Bottom Layout Guide.Top = Root Stack View.Bottom + 20.0
- Image View.Height = Image View.Width
- First Name Text Field.Width = Middle Name Text Field.Width
- First Name Text Field.Width = Last Name Text Field.Width
属性
每个stack都有自己的一系列属性。这些属性定义了每个stack如何布局自身内容。在属性检查器中,设置如下属性:
Stack | Axis(坐标轴) | Alignment(垂直轴方向) | Distribution(沿轴方向) | Spacing(间距) |
---|---|---|---|---|
First Name | Horizontal | First Baseline | Fill | 8 |
Middle Name | Horizontal | First Baseline | Fill | 8 |
Last Name | Horizontal | First Baseline | Fill | 8 |
Name Rows | Vertical | Fill | Fill | 8 |
Upper | Horizontal | Fill | Fill | 8 |
Button | Horizontal | First Baseline | Fill Equally | 8 |
Root | Vertical | Fill | Fill | 8 |
此外,CHCR属性定义了相关视图应该拉伸来填充可用空间。在尺寸检查器中,设置如下CHCR属性:
名称 | Horizontal hugging(水平抗拉伸) | Vertical hugging(垂直抗拉伸) | Horizontal resistance(水平抗压缩) | Vertical resistance(水平抗压缩) |
---|---|---|---|---|
Image View | 250 | 250 | 48(易被压缩) | 48(易被压缩) |
Text View | 250 | 249(易被拉伸) | 250 | 250 |
First, Middle, and Last Name Labels | 251 | 251 | 750(不易被压缩) | 750(不易被压缩) |
First, Middle, and Last Name Text Fields | 48(易被拉伸) | 250 | 749 | 750 |
讨论
在此做法中,多个stack view共同作用来处理绝大多数的布局。但是,他们不能仅仅通过自身创建出所有需要的行为。比如,当image view尺寸变化时,图片应该可以保持自身的宽高比。不幸的是,在单独的Stack View的做法在这里不起作用。布局需要尽可能同时适配图片的尾部和底部边界,且使用按比例适配(Aspect Fit)模式会给某些尺寸上增加额外空白。幸运的是,在本例中,图片的宽高比例总是正方形,所以你可以让图片完整填充image view的边界,并以1:1的比例拉伸image view。
说明
在Interface Builder,宽高比(Aspect Ratio)约束简单来说就是视图自身宽高的约束。Interface Builder还可以用许多方式显示约束的倍数。一般来说,对于宽高比约束,将其显示为比例。因此,一个View.Width = View.Height约束可以显示为1:1的宽高比。
此外,所有的text field应该拥有相同宽度。不幸的是,他们都在不同的stack view中,所以stack无法处理这种情况。因此,你必须添加明确的等宽约束。
像单独的stack view一样,你还必须修改一些CHCR属性。这些定义了视图在父视图尺寸改变时如何缩放。
在垂直方向上,你需要扩大text view,使其填充上部分stack和按钮stack视图以外的空间。因此,text view的垂直抗拉伸优先级必须必其他两者更低才行。
在水平方向上,所有的label应该以真实内容尺寸进行展示,同时所有的text field需要调整尺寸来填满额外空间。label的默认CHCR属性被Interface Builder调整的很好。它已经将抗拉伸约束设置为251,使其比text field的要高;可是,你还是需要同时调低text field的水平抗拉伸和抗压缩优先级。
当stack包含name rows时,image view应该压缩以保持相同高度。可是,所有的stack view只是简单的环绕着自身内容。这意味着image view的垂直抗压缩优先级必须非常低,才会使image view压缩而不是将外部的stack view撑大。此外,image view的宽高比约束使布局变复杂,因为它允许了水平和竖直约束进行交互。这意味着text field的水平抗拉伸优先级也必须非常低,否则他们会阻止image view的压缩。综合以上所有情况,将优先级的值设置为48或更低。