Search code examples
iosswiftswiftuiscrollviewlazyvgrid

SwiftUI LazyVGrid with scroll view issue


The text "Bottom Text" is intended to occupy some space at the bottom. However, when using a LazyVGrid with a scroll view, the content ends up being rendered behind the bottom text, and the scrollable area appears to stretch beyond the screen.

How can this issue be resolved?

Expected

Expected

Actual

Actual

struct HFlexibleView<Content: View>: View {
    let triggerWidth: CGFloat
    let content: () -> Content
    ///If this is set true, the view will be rendered normally, insead of being arranged flexibly
    var disabled: Bool
    var maxmumWidth: CGFloat
    var columns: [GridItem] {
        [GridItem(.adaptive(minimum: triggerWidth,
                            maximum: maxmumWidth))]
    }
    
    init(triggerWidth: CGFloat,
         maxmumWidth: CGFloat = .infinity,
         disabled: Bool = false,
         @ViewBuilder content: @escaping () -> Content) {
        self.triggerWidth = triggerWidth
        self.maxmumWidth = maxmumWidth
        self.disabled = disabled
        self.content = content
    }

    var body: some View {

        if disabled {
            content()
        } else {
            GeometryReader { geometry in
                LazyVGrid(columns: columns) {
                    content()
                        .frame(maxWidth: .infinity)
                }

            }
        }
        
    }
}


struct FlexbibleView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            HFlexibleView(triggerWidth: 500) {
                ScrollView {
                    ForEach(0...20, id: \.self) {_ in
                        Image(systemName: "keyboard")
                            .font(.system(size: 30))
                            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 50)
                            .background(Color.green)
                            .cornerRadius(10)
                    }
                }
            }
            Text("Bottom Text")
        }
        
    }
}


Solution

  • The docs for LazyVGrid says: A container view that arranges its child views in a grid that grows vertically, creating items only as needed.

    So you could use a specific size to constrain the content (i.e the ScrollView), such as:

     GeometryReader { geometry in
         LazyVGrid(columns: columns) {
             content()
                 .frame(maxWidth: .infinity, maxHeight: geometry.size.height)
         }
     }