问题是如何获取父视图中实际查看的渲染尺寸和位置?换句话说,如何Text("Foo")在下面的 SwiftUI 代码中获取实际大小?
GeometryReader 可用于获取父建议size和安全区域插入 via safeAreaInsets,这些信息在 内部定义GeometryProxy。从下面的截图中您可以看到,建议的尺寸为VStack宽度300和300高度,实际尺寸VStack未知。
struct FooView: View {
var body: some View {
GeometryReader { geometryProxy in
VStack {
Text("\(geometryProxy.size.height), \(geometryProxy.size.width)")
Text("Foo")
}
.background(Color.green)
}
.frame(width: 300, height: 300)
.background(Color.blue)
}
}
Run Code Online (Sandbox Code Playgroud)
实际渲染尺寸
.background解决方法是通过带有嵌套的修饰符来获取实际渲染的大小GeometryReader。然后,新几何代理内的尺寸信息可以存储在@State视图中定义的临时变量中。
struct FooSizePreferenceKey: PreferenceKey {
static let defaultValue = CGSize.zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
struct FooView: View {
@State private var fooSize: CGSize = .zero
var body: some View {
GeometryReader { geometryProxy in
VStack {
Text("\(self.fooSize.height), \(self.fooSize.width)")
Text("Foo")
.background(
GeometryReader { fooProxy in
Color
.green
.preference(key: FooSizePreferenceKey.self,
value: fooProxy.size)
.onPreferenceChange(FooSizePreferenceKey.self) { size in
self.fooSize = size
}
}
)
}
}
.frame(width: 300, height: 300)
.background(Color.blue)
}
}
Run Code Online (Sandbox Code Playgroud)
实际渲染位置
视图的实际渲染位置可以使用Anchor和 来计算anchorPreference。使用anchor和parent ,我们可以轻松获取目标视图的geometryProxy位置信息。.bound
struct FooAnchorData: Equatable {
var anchor: Anchor<CGRect>? = nil
static func == (lhs: FooAnchorData, rhs: FooAnchorData) -> Bool {
return false
}
}
struct FooAnchorPreferenceKey: PreferenceKey {
static let defaultValue = FooAnchorData()
static func reduce(value: inout FooAnchorData, nextValue: () -> FooAnchorData) {
value.anchor = nextValue().anchor ?? value.anchor
}
}
struct FooView: View {
@State private var foo: CGPoint = .zero
var body: some View {
GeometryReader { geometryProxy in
VStack {
Text("\(self.foo.x), \(self.foo.y)")
Text("Foo")
.background(
GeometryReader { fooProxy in
Color
.green
.anchorPreference(key: FooAnchorPreferenceKey.self,
value: .bounds,
transform: {FooAnchorData(anchor: $0) })
.onPreferenceChange(FooAnchorPreferenceKey.self) { data in
self.foo = geometryProxy[data.anchor!].origin
}
}
)
}
}
.frame(width: 300, height: 300)
.background(Color.blue)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3116 次 |
| 最近记录: |