Pondorasti
Pondorasti

Reputation: 627

SwiftUI: How to create LazyGrid with equal number of rows and columns?

I am trying to create a grid in SwiftUI 2 using the new primitives LazyVGrid/LazyHGrid.

My goal is to create a grid with the following properties:

Here's a video with the expected results. This was achieved by a custom Grid object that uses GeometryReader.

enter image description here

I've tried using .contentMode(1, .fit) to restrain the LazyVGrid to a 1:1 ratio but it doesn't seem to work. The red background represents the frame of the Grid which is not the expected behaviour.

LazyVGrid(columns: [GridItem(.adaptive(minimum: 32), spacing: 0)], spacing: 0) {
    ForEach(1...100, id: \.self) { item in
        Rectangle()
            .aspectRatio(1, contentMode: .fit)
            .border(Color.black)
    }
}
.aspectRatio(1, contentMode: .fit)
.background(Color.red)

Grid Attempt

I have also tried using GeometryReader to fix the size of the LazyVGrid, but it still didn't work. Any other ideas on how to achieve this?

Upvotes: 6

Views: 8743

Answers (3)

Asperi
Asperi

Reputation: 257779

Try the following (tested with Xcode 12b3 / iOS 14, no big-sur)

struct TestGridFitView: View {
    let columns = Array(repeating: GridItem(.flexible(minimum: 32), spacing: 0), count: 10)
    var body: some View {
        LazyVGrid(columns: columns, spacing: 0) {
            ForEach(1...100, id: \.self) { item in
                Rectangle().fill(Color.clear)
                    .aspectRatio(1, contentMode: .fit)
                    .border(Color.black)
            }
        }
        .background(Color.red)
        .aspectRatio(contentMode: .fit)
        
    }
}

Upvotes: 9

Pondorasti
Pondorasti

Reputation: 627

After seeing @Asperi's solution above, I've managed to solve the final piece of the puzzle. Here's the code:

var body: some View {
    let columns = Array(repeating: GridItem(.flexible(minimum: 4, maximum: 48), spacing: 0), count: 10)

    LazyVGrid(columns: columns, spacing: 0) {
        ForEach(1...100, id: \.self) { item in
            Rectangle()
                .aspectRatio(1, contentMode: .fit)
                .border(Color.black)
        }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
    .aspectRatio(1, contentMode: .fit)
    .background(Color.red)
}

Final Product

Upvotes: 7

MarcoCarnevali
MarcoCarnevali

Reputation: 668

Have you tried giving an infinity max width? Like this:

    LazyVGrid(columns: [GridItem(.adaptive(minimum: 32), spacing: 0)], spacing: 0) {
    ForEach(1...100, id: \.self) { item in
        Rectangle()
            .aspectRatio(1, contentMode: .fit)
            .border(Color.black)
    }
}
.frame(maxWidth: .infinity)
.background(Color.red)

Upvotes: 0

Related Questions