Best way to make a grid with both top and left headers

Hello,

I’d like to display items in a grid, with both a header row and a header column. Something like this :

  A B C D
1 x y x x
2 x x x x
3 x y y y
4 y x x y

What elements should I use for this arrangement?

It seems Grid doesn’t allow for headers that would behave differently than the data cells, and, if using a separate HStack or VStack for the headers, I’m not sure how I could force data lines and rows to stay aligned with the headers.

Answered by Vision Pro Engineer in 749776022

You can definitely use Grid for this! You can do something like this:

             Grid{
                GridRow {
                    ForEach(0..<3) { _ in
                        Text("header")
                            .padding()
                    }
                }
                ForEach(0..<3){ num in
                    GridRow {
                        Text("\(num)")
                            .padding()
                        
                        ForEach(0..<2) { _ in
                            Text("X")
                                .padding()
                        }
                    }
                }
            }

The first GridRow would iterate through your data for your headers. Here, I have 3 headers as I will only be using 3 columns for my data.

Then, I have a ForEach that gives me 3 more GridRows. Each of these contain the label for the vertical axis label and then another ForEach that contains the data for that row.

This gives you both vertical and horizontal axis labels and the data is laid out by row.

Accepted Answer

You can definitely use Grid for this! You can do something like this:

             Grid{
                GridRow {
                    ForEach(0..<3) { _ in
                        Text("header")
                            .padding()
                    }
                }
                ForEach(0..<3){ num in
                    GridRow {
                        Text("\(num)")
                            .padding()
                        
                        ForEach(0..<2) { _ in
                            Text("X")
                                .padding()
                        }
                    }
                }
            }

The first GridRow would iterate through your data for your headers. Here, I have 3 headers as I will only be using 3 columns for my data.

Then, I have a ForEach that gives me 3 more GridRows. Each of these contain the label for the vertical axis label and then another ForEach that contains the data for that row.

This gives you both vertical and horizontal axis labels and the data is laid out by row.

Great, thank you @sha921 !

However, the first column will not have the same size as the others. Any way to do this?

I’d like all columns to have the same size. (Without providing an explicit, fixed size.)

Using

private var columns: [GridItem] = [
          GridItem(.fixed(100)),
          GridItem(.fixed(100)),
          GridItem(.fixed(100))
      ]

is the best way to guarantee them to be the same size. Using .flexible will allow to you either set nothing or the min/max. The size will change depending on the content though (and same with adaptive ). For this, you can ensure equal column widths if you make the header the same width for each column.

Best way to make a grid with both top and left headers
 
 
Q