案例分析
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Text("Hello, SwiftUI!")
.background(Color.blue)
.coordinateSpace(name: "CustomSpace")
.onTapGesture {
print("Tapped")
}
Spacer()
}
.overlay(
GeometryReader { proxy in
let frame = proxy.frame(in: .named("CustomSpace"))
Text("Text Position: \(frame.debugDescription)")
.position(x: 100, y: 100)
}
)
}
}
在这段代码中,GeometryReader内部的Text偏移可能会让人产生疑惑,那就是这里的position(x:100, y:100)按理说,应该是对齐视图左上角的(100,100),但出现的位置却在视图的中间部分。
尝试给GeometryReader添加一个绿色背景时,会发现GeometryReader也不是占据整个屏幕,而是仅在屏幕的内部居中:
GeometryReader { proxy in
let frame = proxy.frame(in: .named("CustomSpace"))
Text("Text Position: \(frame.debugDescription)")
.position(x: 100, y: 100)
}
.background(Color.green)
原因分析
GeometryReader 的大小受父视图影响
GeometryReader 本质上是一个容器视图,它会尽量填满父视图赋予的空间。如果它直接被嵌套在 .overlay 修饰符中,而没有显式指定大小,则它会默认收缩到子视图的固有内容大小。
在代码中:
.overlay(
GeometryReader { proxy in
let frame = proxy.frame(in: .named("CustomSpace"))
Text("Text Position: \(frame.debugDescription)")
.position(x: 0, y: 0)
}
.background(Color.green)
)
GeometryReader 的唯一子视图是 Text,而 Text 的固有大小非常小。
因此,GeometryReader 的实际大小收缩为子视图 Text 的固有大小,而不是覆盖整个父视图。
Text的position偏移问题
尝试将Text的position置为0:
GeometryReader { proxy in
let frame = proxy.frame(in: .named("CustomSpace"))
Text("Text Position: \(frame.debugDescription)")
.position(x: 0, y: 0)
}
.background(Color.green)
既然GeometryReader在中间,Text置为0后,应该出现在GeometryReader的左上角。
实际出现的位置是屏幕的左上角和GeometryReader左上角中间的位置。
这是因为这里的Text的position(x:0 y:0) 设置的是Text的顶部中心点对准GeometryReader视图的中心点位置。
因此,最开始的视图内容就可以得到合理的解释。