一 布局法则
- 父view为子view提供一个建议的size,并询问子视图的大小
- 子view根据自身的特性,返回一个size
- 父view根据子view返回的size为其进行布局
二 布局中立
布局中立 (layout neutral):本身没有任何大小,而是可以根据需要进行调整以适应任何大小。
三 View计算自己的Size
在SwfitUI中,view在计算自己size的时候会有不同的行为方式,我们分为4类:
- 类似于
Vstack
,它们会尽可能让自己内部的内容展示完整,但也不会多要其他的额外空间 - 类似于
Text
这种只返回自身需要的size,如果size不够,它非常聪明的做一些额外的操作,比如换行等等 - 类似于
Shape
这种给多大尺寸就使用多大尺寸 - 还有一些可能超出父控件的view
还存在其他一些比较特殊的例外,比如Spacer
,他的特性跟他属于哪个容器或者哪个轴有关系。当他在VStack
中时,他会尽可能的占据剩余垂直的全部空间,而占据的水平空间为0,在HStack
中,他的行为却又恰恰相反。
3.1 例子
struct LayoutView: View {
var body: some View {
Text("Hello, World!")
.frame(width: 200, height: 100)
.background(Color.green)
.frame(width: 400, height: 200)
.background(Color.orange.opacity(0.5))
}
}
- 对于LayoutView,其父View给他的建议尺寸为整个屏幕大小
我们先考虑LayoutView,他的父view给他的建议尺寸为整个屏幕的大小,我们称为size0,他去询问他的child,他的child为最下边的那个background,这个background自己也不知道自己的size,因此他继续拿着size0去询问他自己的child,他的child是个frame,返回了width400, height200, 因此background告诉ContentView他需要的size为width400, height200,因此最终ContentView的size为width400, height200。
很显然,我们也计算出了最下边background的size,注意,里边的Color也是一个view,Color本身是一个Shape,background返回一个透明的view
我们再考虑最上边的background,他父view给的建议的size为width: 400, height: 200,他询问其child,得到了需要的size为width: 200, height: 100,因此该background的size为width: 200, height: 100。
我们在看Text,父View给的建议的size为width: 200, height: 100,但其只需要正好容纳文本的size,因此他的size并不会是width: 200, height: 100
image.png
3.2
var body: some View {
VStack{
Text("Hello, world 1")
.border(Color.green)
Text("Hello, world 2")
.border(Color.green)
.frame(width: 200, height: 50)
.border(Color.red)
Text("Hello, world 3")
.frame(width: 200, height: 50)
.border(Color.green)
}
}
image.png
布局说明:
VStack为垂直布局容器,为子View提供一个建议的size,为全屏幕的尺寸
在SwiftUI中修饰符的顺序很重要,不同的顺序产生不同的结果
参考:
网友评论