swiftuilazyvgrid

Starting a grid from the bottom left


I would like to create a grid that is similar to a chess layout and labeled from 1 to 100 starting at the bottom left. It should look somewhat like this:

...

5(white) 6(black) 7(white) 8(black)

1(black) 2(white) 3(black) 4(white)

I cannot get the labeling or coloring to display correctly. This is my attempt. How can I adjust it?

import SwiftUI

struct LevelOverviewView: View {
    
    let numberOfLevels = 100
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: Array(repeating: GridItem(.fixed(70)), count: 4), content: {
                ForEach((1...numberOfLevels).reversed(), id: \.self) { i in
                    ZStack{
                        Rectangle()
                            .fill(i % 2 == 0 ? .black : .white)
                            .aspectRatio(1.0, contentMode: .fit)
                        Text("\(i)")
                            .foregroundStyle(i % 2 == 1 ? .black : .white)
                    }
                }
            })
        }
        .background(.red)
    }
}

#Preview {
    LevelOverviewView()
}

enter image description here


Solution

  • You could try this approach reversing the numbers in steps of 4, as shown in the example code:

    struct ContentView: View {
        var body: some View {
            LevelOverviewView()
        }
    }
    
    struct GridCell: Identifiable {
        let id = UUID()
        var value: Int
    }
    
    
    struct LevelOverviewView: View {
        @State private var gridCell: [GridCell] = []
        let numberOfLevels = 100
        let step = 4 // <--- here, adjust as desired
        
        var body: some View {
            ScrollView {
                LazyVGrid(columns: Array(repeating: GridItem(.fixed(70)), count: step)) {
                    ForEach(gridCell) { cell in
                        ZStack {
                            Rectangle()
                                .fill(cell.value % 2 == 0 ? .black : .white)
                                .aspectRatio(1.0, contentMode: .fit)
                            Text("\(cell.value)")
                                .foregroundStyle(cell.value % 2 == 1 ? .black : .white)
                        }
                    }
                }
            }
            .background(.red)
            .onAppear {
                gridCell = (1...numberOfLevels).map{ GridCell(value: $0) }.reversed()
                
                // --- here
                for i in stride(from: 0, to: gridCell.count, by: step) {
                    let endIndex = min(i + step, gridCell.count)
                    gridCell[i..<endIndex].reverse()
                }
            }
        }
    }