1
votes

When adding a standard Scrollview I can scroll to the end of my list without any issues, it's after adding a GeometryReader on my button that the scroll list doesn't scroll to the end of the list but stops somewhere at the top of my button. The geometryReader does not scale to the size of the child object, how can I change this without specifying a hard coded frame size for the GeometryReader ? I'm using the GeometryReader to later identify the top of my button corresponding the position on the screen with geo.frame(in: .global).maxY

struct scroll: View {
    
    private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible())]
    
    var body: some View {
        ScrollView {
            VStack {
                LazyVGrid(columns: gridItemLayout) {
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.red)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.green)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.blue)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.yellow)
                }
                GeometryReader { geo in
                    Button(action: {
                        
                    }) {
                        Text("Adjust time")
                    }
                    .cornerRadius(18.0)
                    .padding(.top, 5)
                }
                //.frame(width: .infinity, height: 50)
                
            }
        }
    }
}

When checking the height and trying to set the frame of the GeometryReader equal to the height of the button, the button it also gives me 0 as value. When I try to read the width of the button with geo.frame.width, it gives me a correct value.?

struct scroll: View {
    
    private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible())]
    
    @State private var buttonHeight: CGFloat = .zero
    
    var body: some View {
        ScrollView {
            VStack {
                Text("\(buttonHeight)")
                LazyVGrid(columns: gridItemLayout) {
                    
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.red)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.green)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.blue)
                    Circle()
                        .scaledToFill()
                        .foregroundColor(.yellow)
                }
                GeometryReader { geo in
                    
                    Button(action: {
                        
                    }) {
                        Text("Adjust time")
                    }
                    .onAppear(perform: {
                        buttonHeight = geo.size.height
                    })
                    .cornerRadius(18.0)
                    .padding(.top, 5)
                }
                .frame(width: .infinity, height: buttonHeight)
                .background(Color.gray)
                
            }
        }
    }
}
1

1 Answers

1
votes

You can read it by putting GeometryReader into background of button, like

Button(action: {
    
}) {
    Text("Adjust time")
}
.cornerRadius(18.0)
.padding(.top, 5)
.background(GeometryReader { geo in
   // geo.frame(in: .global).maxY      // << global position of button
})

You can then even store it in view preference to pass into state, like in https://stackoverflow.com/a/62466397/12299030.