当我们需要嵌套多级Stack进行一些较为复杂的布局时,通常会比较头疼,不知道为什么布局的效果和我们想象的有差异,这时候会视图通过frame这个Modifier来调整效果,一顿操作后,效果是OK了,但代码的可读性和扩展性就。。。
布局的讲解,将分为两部分:
- 默认情况下的子视图布局方式
- frame/layoutPriority对子视图布局的影响
这一节我们来一起看看,SwiftUI的一些内置规范,帮助我们来理解Stack是如何处理自己的Child View的,有了这样的理解后,可以帮助更高效的调整布局。
先来看看一些内置规则,前提是子视图均没有设置frame/priority modifier,再通过实例来解释:
- 父视图给出了可用于布局(可以自己支配)的frame;
- 当有多个子视图时,在子视图中进行挑选找固有size(UIKit中也有这个概念)最小的,当固有size也相同时,选择第一个子视图。
- 对第二步找到的子视图进行布局,把自己的可支配的大小进行均分,将其中之一划分给这个子视图进行布局
- 子视图基于父视图提供的frame来看看自己到底占据的大小
- 子视图算好之后,父视图会减去这个子视图所占据的size,把剩下的部分分配给其余的子视图,回到步骤2,进行下一次循环,直到所有子视图绘制完成。
- 当所有子视图绘制结束后,父视图再根据子视图所占据空间来调整自己的size
感觉有点绕,让我找个HStack
的例子来演示一下:
示例
struct DemoView: View {
var body: some View {
HStack {
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}.background(Color.yellow)
}
}
两段文字的大小是相同的,想象中,他们应该是等宽的,但是结果出乎意料:
two-subviews.png
我们来一起过一遍之前的布局规则:
- HStack作为父视图,它可以支配的大小是整个页面,所以两个Text,可以沾满整个页面;
- 第二步中,因为两个Text完全相同,就取了第一个Text;
- 父视图将自己的可以用空间分为两份,将第二步中找到的视图进行布局,这个Text发现在二分之一的是空间内,无法一行显示,只能用两行;
- 当需要放两行时,它尽可能的使用最少的空间,就将自己的文字均分为两行,结果就是上图中的一个Text的样子;
- 第一个子视图绘制结束之后,将剩下的空间给了剩余的子视图,也就是第二个Text。
回到第二步,第二个Text试图在一行内放下所有的文字,可放不下,于是进行了折行。
- 布局完所有的子视图,父视图发发现并没有利用完所有的屏幕横向空间,再根据两个Text所占据的空间调整了自己的大小,于是就有了两边的留白。
真的是这样么?我们再做一个小实验,更改一些第二个Text中的文字,将warm -> warn,一个字母的差别将影响第二步中选择最小固有size视图的结果,看看结果会是怎样的:
two-subviews2.png
这个结果源于第二步中,选择了固有size最小的,也就是第二个Text,先进行布局。
当我们想要根据需求来更改一些默认的行为时,就需要借助fram/layoutPriority这两个modifier了,下周继续更新~
网友评论