SwiftUI 测量视图的高度

问题描述

我尝试使用 coordinatespace 测量视图的高度,但它返回的值是全屏的高度。知道为什么我的代码没有给我我想要的吗?

struct GeoReader: View {
    var body: some View {
        GeometryReader { geo in
            vstack {
                ZStack {
                    Rectangle()
                        .foregroundColor(.blue)
                    Text("Heigt of full screen is \(geo.size.height)")
                }
                ZStack {
                    Rectangle()
                        .foregroundColor(.red)
                        .coordinateSpace(name: "RedBox")
                    Text("Height of red Box is \(geo.frame(in: .named("RedBox")).height)")
                }
            }
        }
    }
}

enter image description here

解决方法

几何阅读器测量整个屏幕,因为您将几何阅读器放在视图主体的顶部。因此,它将读取它返回的视图的几何形状。在本例中为整个屏幕。

如果你想得到两个矩形的大小,你应该把几何阅读器放在矩形和文本的堆栈中。

struct GeoReader: View {
    var body: some View {
        GeometryReader { geo1 in
            VStack {
                ZStack {
                    Rectangle()
                        .foregroundColor(.blue)
                    Text("Heigt of full screen is \(geo1.size.height)")
                }
                ZStack {
                    GeometryReader { geo2 in
                        Rectangle()
                            .foregroundColor(.red)
                            .coordinateSpace(name: "Redbox")
                        Text("Height of red box is \(geo2.frame(in: .named("Redbox")).height)")
                    }
                }
            }
        }
    }
}
,

显示尺寸是作为内部视图容器的完整视图的尺寸。

您需要使用另一个 GeometryReader 来获取第二个 ZStack 的内部维度。

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            VStack {
                ZStack {
                    Rectangle()
                        .foregroundColor(.blue)
                    Text("Heigt of full screen is \(geo.size.height)")
                }
                GeometryReader { innterGeo in //<Here
                    ZStack {
                        Rectangle()
                            .foregroundColor(.red)
                            .coordinateSpace(name: "Redbox")
                        Text("Height of red box is \(innterGeo.frame(in: .named("Redbox")).height)")
                    }
                }
            }
        }
    }
}

如果你需要在任何地方使用它,那么你可以使用这个方法。

首先,创建一个结构体并使用 GeometryReader 包装您的内容。

struct GeometryContentSize<Content: View>: View {
    public var content: (CGSize) -> Content
    
    var body: some View {
        GeometryReader { geo in
            content(geo.size)
        }
    }
}

用法:

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            VStack {
                ZStack {
                    Rectangle()
                        .foregroundColor(.blue)
                    Text("Heigt of full screen is \(geo.size.height)")
                }
                
                GeometryContentSize { (size) in //<--- Here
                    ZStack {
                        Rectangle()
                            .foregroundColor(.red)
                        Text("Height of red box is \(size.height)")
                    }
                }
            }
        }
    }
}