walker
walker

Reputation: 767

How to use LazyVGrid to implement a grid where every cell is different width, thus every row have different number of cells

I've tried .adaptive(min: max), but the layout system just calculates the first row to determine how many cells per row then applies this to every row. So it creates many overlaps. If everything were to go right as expected, every row should have a different number of cells because of the different widths.

Here is my code:

import SwiftUI

struct MyLazyVGrid: View {

    private let cardHeight: CGFloat = 90
    private let spacing: CGFloat = 10
    private let minWidth = 50.0
    private let maxWidth = 120.0
    
    private func randomWidth() -> CGFloat {
        CGFloat.random(in: minWidth...maxWidth)
    }
    private func randomColorPart() -> CGFloat {
        CGFloat.random(in: 0.0...1.0)
    }
    
    private func randomColor() -> Color {
        Color.init(red: randomColorPart(), green: randomColorPart(), blue: randomColorPart()).opacity(0.7)
    }
    
    private var cardData: [CGFloat] {
        (0..<100).map { _ in randomWidth() }
    }
    
    var body: some View {
        let gridItems = [GridItem(.adaptive(minimum: minWidth, maximum: maxWidth), spacing: 20.0)]
        
        ScrollView {
            LazyVGrid(columns: gridItems, spacing: spacing) {
                ForEach(cardData.indices, id: \.self) { index in
                    Rectangle()
                        .fill(randomColor())
                        .frame(width: cardData[index], height: cardHeight)
                        .overlay(
                            Text("\(index)")
                                .foregroundColor(.white)
                        )
                }
            }
            .padding()
        }
    }
}

#Preview {
    MyLazyVGrid()
}

output:

the output

It's very common in UICollectionView's FlowLayout. Is this scenario originally supported by SwiftUI?

Upvotes: 0

Views: 68

Answers (0)

Related Questions