回答标题中的问题:
- 可以将
GeometryReader
包装在.overlay()
或.background()
中,这样可以缓解GeometryReader的布局变化效果。 视图将按通常的方式布局,GeometryReader将扩展到视图的完整大小并将geometry
发射到其内容构建器闭包中。
- 还可以设置GeometryReader的框架以停止其扩展的急切性。
例如,此示例通过将GeometryReader包装在覆盖层中,在3/4矩形高度内呈现蓝色矩形和“Hello world”文本(而不是矩形填充所有可用空间):
struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.overlay(GeometryReader { geo in
Text("Hello world").padding(.top, geo.size.height * 3 / 4)
})
Spacer()
}
}
通过在 GeometryReader 上设置框架来实现相同效果的另一个示例:
struct MyView : View {
var body: some View {
GeometryReader { geo in
Rectangle().fill(Color.blue)
Text("Hello world").padding(.top, geo.size.height * 3 / 4)
}
.frame(height: 150)
Spacer()
}
}
![渲染出一个蓝色矩形的三分之四高度上方显示"Hello world"的图像。](https://istack.dev59.com/b2xDbm.webp)
然而,有些注意事项/行为并不是非常明显
1
视图修饰符应用到它们被应用的位置之前的所有内容,而不是之后的内容。在.edgesIgnoringSafeArea(.all)
之后添加的覆盖物/背景将尊重安全区域(不参与忽略安全区域)。
此代码在安全区域内呈现“Hello world”,而蓝色矩形则忽略了安全区域:
struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.edgesIgnoringSafeArea(.all)
.overlay(VStack {
Text("Hello world")
Spacer()
})
Spacer()
}
}
![“Hello world” 在安全区域内的渲染效果。](https://istack.dev59.com/ZudHem.webp)
2
将.edgesIgnoringSafeArea(.all)
应用于背景,会使GeometryReader忽略安全区域:
struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.overlay(GeometryReader { geo in
VStack {
Text("Hello world")
.padding(.top, geo.safeAreaInsets.top)
Spacer()
}
})
.edgesIgnoringSafeArea(.all)
Spacer()
}
}
![忽略安全区域的“Hello world”渲染图。](https://istack.dev59.com/P6fbXm.webp)
通过添加多个覆盖层/背景可以组合出许多布局。
3
测量的几何信息将对GeometryReader的内容可用。而不是父视图或兄弟视图;即使值提取到State或ObservableObject中,SwiftUI也会发出运行时警告:
struct MyView : View {
@State private var safeAreaInsets = EdgeInsets()
var body: some View {
Text("Hello world")
.edgesIgnoringSafeArea(.all)
.background(GeometryReader(content: set(geometry:)))
.padding(.top, safeAreaInsets.top)
Spacer()
}
private func set(geometry: GeometryProxy) -> some View {
self.safeAreaInsets = geometry.safeAreaInsets
return Color.blue
}
}
![运行时警告“在视图更新期间修改状态,这将导致未定义的行为。”](https://istack.dev59.com/SEXFS.webp)
HStack
的VStack
。我在 Xcode 预览和模拟器中都进行了检查,结果相同。在您的预览提供程序中尝试使用此代码:MyView().previewLayout(.sizeThatFits)
。 - Infinity