Search code examples
swiftuidatatablelazyvgrid

SwiftUI LazyVGrid missing some content


I have been experimenting with LazyVGrid to produce a table with grid lines. I'm using XCode 13.4 & iOS15. Everything seemed to be going well until I parameterized all the column sizes, line widths, etc. The content consists of an array of row data with 5 pieces of text in each row. Here is the code:

struct StatisticsView: View {
    
    private let columnMinWidths: [CGFloat] = [120, 50, 50, 50, 50]
    private let rowHeight: CGFloat = 40
    private let thinGridlineSize: CGFloat = 0.5
    private let thickGridlineSize: CGFloat = 2
    private let lineColour = Color.accentColor
    
    private let columns: [GridItem]
    
    private let rowContents = [
        ["Player's name", "Graham", "John", "Archie", ""],
        ["Round 1", "2", "3", "1", ""],
        ["Round 2", "3", "-", "2", ""],
        ["Round 3", "1", "2", "4", ""],
        ["Round 4", "2", "1", "1", ""]
    ]
    
    init() {
        self.columns = [
            GridItem(.fixed(thickGridlineSize), spacing: 0),
            GridItem(.flexible(minimum: columnMinWidths[0]), spacing: 0),
            GridItem(.fixed(thickGridlineSize), spacing: 0),
            GridItem(.flexible(minimum: columnMinWidths[1]), spacing: 0),
            GridItem(.fixed(thinGridlineSize), spacing: 0),
            GridItem(.flexible(minimum: columnMinWidths[2]), spacing: 0),
            GridItem(.fixed(thinGridlineSize), spacing: 0),
            GridItem(.flexible(minimum: columnMinWidths[3]), spacing: 0),
            GridItem(.fixed(thinGridlineSize), spacing: 0),
            GridItem(.flexible(minimum: columnMinWidths[4]), spacing: 0),
            GridItem(.fixed(thickGridlineSize), spacing: 0),
        ]
    }
    
    var body: some View {
        VStack(spacing: 0) {
            // top horizontal gridline
            lineColour.frame(height: thickGridlineSize)
            LazyVGrid(columns: columns, alignment: .leading, spacing: 0) {
                ForEach(0..<rowContents.count, id: \.self) { row in
                    lineColour.frame(height: rowHeight)
                    ForEach(0..<rowContents.first!.count, id: \.self) { col in
                        // cell contents with bottom gridline
                        VStack(spacing: 0) {
                            Text(rowContents[row][col])
                                .font(.caption2)
                                .frame(height: rowHeight - thinGridlineSize)
                            // tried using a colour fill but same result
                            // Color.green
                            //    .frame(height: rowHeight - thinGridlineSize)
                            lineColour.frame(height: thinGridlineSize)
                        }
                        // vertical gridline between cells
                        lineColour.frame(height: rowHeight)
                    }
                }
            }
            // bottom horizontal gridline
            lineColour.frame(height: thickGridlineSize)
        }
        .padding(.horizontal, 8)
    }
}

and here is what is being displayed on the simulator screen:

enter image description here

Can anyone see where I'm going wrong here? Any help would be much appreciated. Thanks.


Solution

  • You have to remove id: \.self from both loops. View Id become duplicated so it's not drawing more than one line.

    enter image description here