Search code examples
swiftuigeometryreader

SwiftUI measuring the height of a view


I tried measuring the height of a view by using coordinatespace on it but the value it returns is the height of the full screen. Any idea why my code isn't giving me what I want ?

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


Solution

  • The showing size is the dimension of the full view that is the container of the inner view.

    You need to use another GeometryReader to get the inner dimension of a second 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)")
                        }
                    }
                }
            }
        }
    }
    

    if you need to use this in any places then you can use this approch.

    First, create one struct and wrapped your content with GeometryReader.

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

    usage:

    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)")
                        }
                    }
                }
            }
        }
    }