4

I've got a LazyHGrid that shows multiple Text views in one row. That LazyHGrid is inside a VStack. However, the LazyHGrid is higher than it needs to be. What causes the extra space?

struct ContentView: View {

    let rows = [GridItem()]

    var body: some View {
        VStack {
        
            ScrollView(.horizontal) {
                LazyHGrid(rows: rows) {
                    ForEach(0..<10) { index in
                        Text("Test \(index)")
                            .padding()
                            .foregroundColor(Color.white)
                            .background(Color.black)
                    }
                }
            }
            .background(Color.green)
        
            ScrollView(.vertical) {
                VStack {
                    ForEach(0..<100) { index in
                        Text(String(index))
                            .frame(maxWidth: .infinity)
                    }
                }
            }
            .background(Color.blue)
        }
    }
}

enter image description here

WalterBeiter
  • 2,021
  • 3
  • 23
  • 48
  • It is not `LazyHGrid`, it is `ScrollView` gets all available space. You have two of them so they divided space equally. – Asperi Feb 09 '22 at 07:27
  • If I remove the ScrollView around the LazyHGrid, the result is the same. – WalterBeiter Feb 09 '22 at 07:29
  • 1
    if possible just set a fixed height to the upper srollview `.frame(height: 100)` ... if you don't want that, read the whole screen height (of both views) with `GeometryReader`and divide the inner heights in some desired ratio (e.g. 1/4 - 3/4) – ChrisR Feb 09 '22 at 07:40
  • that is not an option.. LazyHGrid should be only as high as it needs to. There has to be a way that it determines it's height based on it's content. – WalterBeiter Feb 09 '22 at 08:24

2 Answers2

3

You just have to add .fixedSize() modifier to your grid, and it works...

                LazyHGrid(rows: rows) {
                    ForEach(0..<10) { index in
                        Text("Test \(index)")
                            .padding()
                            .foregroundColor(Color.white)
                            .background(Color.black)
                    }
                }
                .fixedSize()

With fixedSize()

Zaphod
  • 6,758
  • 3
  • 40
  • 60
0

This works: Reading the height of the cells with an overlay with GeometryReader

struct ContentView: View {
    
    let rows = [ GridItem() ]
    @State private var contentSize = CGFloat.zero
    
    var body: some View {
        VStack {
            
            ScrollView(.horizontal) {
                LazyHGrid(rows: rows) {
                    ForEach(0..<10) { index in
                            Text("Test \(index)")
                                .padding()
                                .foregroundColor(.white)
                                .background(.black)
                            
                                .overlay(
                                    GeometryReader { geo in
                                        Color.clear.onAppear {
                                            contentSize = geo.size.height
                                        }
                                    }
                                )

                    }
                }
            }
            .frame(height: contentSize + 20)
            .background(Color.green)
            
            ScrollView(.vertical) {
                VStack {
                    ForEach(0..<100) { index in
                        Text(String(index))
                            .frame(maxWidth: .infinity)
                    }
                }
            }
            .background(Color.blue)
        }
    }
}
ChrisR
  • 9,523
  • 1
  • 8
  • 26