Get width of a view using in SwiftUI

The only available mechanism to get the dimension of a view, that is auto-resized by SwiftUI, is the GeometryReader.
The GeometryReader is a proxy view that returns the dimensions of the container in which your view gets rendered.

struct SomeView: View {
    
    @State var size: CGSize = .zero
    
    var body: some View {
        VStack {
            Text("VStack width: \(size.width)")
            Text("VStack height: \(size.height)")
            
            GeometryReader { proxy in
                HStack {} // just an empty container to triggers the onAppear
                    .onAppear {
                        size = proxy.size
                    }
            }
        }
        
    }
}

The printed size is the dimension of the VStack.

How to get the dimension of a View

Now that we know that the GeometryReader gives us the size of the container, the usual follow-up question is: how do I use it to get the size of a specific view?

To do this we need to move the geometry reader one level below our targeted view. How? We could add an empty background that gets the size of the targeted view and sends this information back to a Binding.

Let’s create a SizeCalculator ViewModifier so that we can use this functionality on every view:

struct SizeCalculator: ViewModifier {
    
    @Binding var size: CGSize
    
    func body(content: Content) -> some View {
        content
            .background(
                GeometryReader { proxy in
                    Color.clear // we just want the reader to get triggered, so let's use an empty color
                        .onAppear {
                            size = proxy.size
                        }
                }
            )
    }
}

extension View {
    func saveSize(in size: Binding<CGSize>) -> some View {
        modifier(SizeCalculator(size: size))
    }
}

The job of the SizeCalculator is to add a GeometryReader as the background of our target view. On appear, so after SwiftUI has rendered the content, it will send the size back to the Binding.

Usage:

struct SomeView: View {
    
    @State var size: CGSize = .zero
    
    var body: some View {
        VStack {
            Text("text width: \(size.width)")
            Text("text height: \(size.height)")
            
            Text("hello")
                .saveSize(in: $size)
        }
        
    }
}

how to get the size of a view in swiftUI

Leave a Comment