Search code examples
swiftuiscrollviewgeometryreader

SwiftUI GeometryReader causing havoc


I have the following view:

var body: some View {
    ScrollView {
        VStack {
            HStack {
                Text("Something")
                Text("Something")
            }
            GeometryReader { geo in
                VStack {
                    CustomView(param: geo.size.width * 0.3) // I need these views to know the size so they can align internal components
                    CustomView(param: geo.size.width * 0.3)
                    CustomView(param: geo.size.width * 0.3)
                }.frame(width: geo.size.width, height: geo.size.height) // Tried also without setting height here
            }
            Button(action: {
                print("Hey")
            }) {
                Text("Push me")
            }
        }.padding()
    }
}

The above results in the portion containing the GeometryReader overlapping the views above, and the Button at the end being on top of the GeometryReader. The result is similar if I wrap the GeometryReader in another VStack.

Is there anyway to fix this behavior? I need the GeometryReader for the reason explained in the code comments (or perhaps and equivalent solution, since I need to size the elements' inner contents in a specific way).


Solution

  • Move GeometryReader outside of ScrollView, like

    var body: some View {
      GeometryReader { geo in     // << here !!
        ScrollView {
            VStack {
                HStack {
                    Text("Something")
                    Text("Something")
                }
                VStack {
                    CustomView(param: geo.size.width * 0.3)
                    CustomView(param: geo.size.width * 0.3)
                    CustomView(param: geo.size.width * 0.3)
                }.frame(width: geo.size.width, height: geo.size.height)
    
                Button(action: {
                    print("Hey")
                }) {
                    Text("Push me")
                }
            }.padding()
        }
      }
    }
    

    *Note: GeometryReader does not work in ScrollView because ScrollView does not have own geometry, it tries to read geometry from content, so there is cycling.