我正在学习SwiftUI,遇到了“GeometryReader”。我想知道什么时候以及为什么要使用它?
自从我发布了这个答案后,我还写了一篇关于 GeometryReader 如何工作的文章。请查看以下链接以获取更详细的解释: https://swiftui-lab.com/geometryreader-to-the-rescue/
GeometryReader 是一个视图,可以让您访问其父视图的大小和位置。例如:
struct MyView: View {
var body: some View {
GeometryReader { geometry in
// Here goes your view content,
// and you can use the geometry variable
// which contains geometry.size of the parent
// You also have function to get the bounds
// of the parent: geometry.frame(in: .global)
}
}
}
我通常与 .background() 结合使用,以获取某些其他视图的边界。例如,文本视图很难预测它将来有多大。当我需要那些信息时,我使用这个技巧:
首先,我定义了一个名为 GeometryGetter 的视图:
struct GeometryGetter: View {
@Binding var rect: CGRect
var body: some View {
return GeometryReader { geometry in
self.makeView(geometry: geometry)
}
}
func makeView(geometry: GeometryProxy) -> some View {
DispatchQueue.main.async {
self.rect = geometry.frame(in: .global)
}
return Rectangle().fill(Color.clear)
}
}
然后,要获取TextView(或任何其他视图)的边界:
struct MyView: View {
@State private var rect: CGRect = CGRect()
var body: some View {
Text("some text").background(GeometryGetter($rect))
// You can then use rect in other places of your view:
Rectangle().frame(width: 100, height: rect.height)
}
}
针对某些用例,我在其他问题中发布了一些使用GeometryReader的答案。请查看以下内容:
移动文本字段以避免被键盘隐藏:https://dev59.com/FVMI5IYBdhLWcg3wUp42#56721268
如何使一个视图的大小与另一个视图相同在SwiftUI中:https://dev59.com/GFMI5IYBdhLWcg3wUp02#56661706
注意:
在GeometryGetter中,我添加了一个DispatchQueue.main.async {}来设置rect。否则,在某些情况下,可能会导致运行时警告: Modifying state during view update。
Reader
?除了kontiki的回答之外,Reader
是一种以函数形式定义其内容的容器视图。因此,它们可以访问和操作其parent
。如果你更仔细地查看,它们是通用的结构体,现在在SwiftUI 2.0中有2个可用的reader:
请注意,这只是一种约定,它们不遵循任何特殊协议,更多的是遵循View
协议。
struct GeometryReader<Content: View> : View
这是一个容器视图,它根据自己的大小和坐标空间定义其内容的函数。因此,您可以检测到GeometryReader
中任何视图的框架和位置更改以及当前状态。其中一个常见用途是在需要将不同的视图分别放置在具有相同(或相对)大小的单独堆栈中时。
struct ScrollViewReader<Content: View> : View
ScrollViewProxy
函数来针对子视图中可滚动的视图进行的。因此,您可以访问一些滚动视图,例如在列表中滚动到特定项或类似功能。
为了减少重复,我没有提供示例,如果您想了解更多信息,请查看链接。
GeometryReader 是一种能够识别父视图几何形状的工具,这意味着当您在几何形状中创建一个视图时,您可以获得父视图的大小。
rect
值而导致无限循环。在 WWDC 22 的 "使用 SwiftUI 组合自定义布局" 会议中讨论了这个问题,具体时间是在 18:20 标记处 https://developer.apple.com/videos/play/wwdc2022/10056/ - chunkyguy