One Logo Pool Ball
SwiftUI · IOS API REFERENCE

Grid

struct · iOS 16.0+ · SDK 27.1

@frozen nonisolated struct Grid<Content> where Content : View

A container view that arranges other views in a two dimensional layout. Create a two dimensional layout by initializing a `Grid` with a collection of ``GridRow`` structures. The first view in each grid row appears in the grid's first column, the second view in the second column, and so on. The following example creates a grid with two rows and two columns: Grid { GridRow { Text("Hello") Image(systemName: "globe") } GridRow { Image(systemName: "hand.wave") Text("World") } } A grid and its rows behave something like a collection of ``HStack`` instances wrapped in a ``VStack``. However, the grid handles row and column creation as a single operation, which applies alignment and spacing to cells, rather than first to rows and then to a column of unrelated rows. The grid produced by the example above demonstrates this: ![A screenshot of items arranged in a grid. The upper-left position in the grid contains the word hello. The upper-right contains an image of a globe. The lower-left contains an image of a waving hand. The lower-right contains the word world. The cells of the grid have minimal vertical or horizontal spacing.](Grid-1-iOS) > Note: If you need a grid that conforms to the ``Layout`` protocol, like when you want to create a conditional layout using ``AnyLayout``, use ``GridLayout`` instead. ### Multicolumn cells If you provide a view rather than a ``GridRow`` as an element in the grid's content, the grid uses the view to create a row that spans all of the grid's columns. For example, you can add a ``Divider`` between the rows of the previous example: Grid { GridRow { Text("Hello") Image(systemName: "globe") } Divider() GridRow { Image(systemName: "hand.wave") Text("World") } } Because a divider takes as much horizontal space as its parent offers, the entire grid widens to fill the width offered by its parent view. ![A screenshot of items arranged in a grid. The upper-left cell in the grid contains the word hello. The upper right contains an image of a globe. The lower-left contains an image of a waving hand. The lower-right contains the word world. A dividing line that spans the width of the grid separates the upper and lower elements. The grid's rows have minimal vertical spacing, but it's columns have a lot of horizontal spacing, with column content centered horizontally.](Grid-2-iOS) To prevent a flexible view from taking more space on a given axis than the other cells in a row or column require, add the ``View/gridCellUnsizedAxes(_:)`` view modifier to the view: Divider() .gridCellUnsizedAxes(.horizontal) This restores the grid to the width that the text and images require: ![A screenshot of items arranged in a grid. The upper-left position in the grid contains the word hello. The upper-right contains an image of a globe. The lower-left contains an image of a waving hand. The lower-right contains the word world. A dividing line that spans the width of the grid separates the upper and lower elements. The grid's rows and columns have minimal vertical or horizontal spacing.](Grid-3-iOS) To make a cell span a specific number of columns rather than the whole grid, use the ``View/gridCellColumns(_:)`` modifier on a view that's contained inside a ``GridRow``. ### Column count The grid's column count grows to handle the row with the largest number of columns. If you create rows with different numbers of columns, the grid adds empty cells to the trailing edge of rows that have fewer columns. The example below creates three rows with different column counts: Grid { GridRow { Text("Row 1") ForEach(0..<2) { _ in Color.red } } GridRow { Text("Row 2") ForEach(0..<5) { _ in Color.green } } GridRow { Text("Row 3") ForEach(0..<4) { _ in Color.blue } } } The resulting grid has as many columns as the widest row, adding empty cells to rows that don't specify enough views: ![A screenshot of a grid with three rows and six columns. The first column contains cells with the labels Row 1, Row 2, and Row 3, reading from top to bottom. The text is centered in the cell in each case. The other columns contain cells that are either filled with a rectangle, or that are empty. Scanning from left to right, the first row contains two red rectangle cells after its label cell, and then three empty cells. The second row contains five green rectangle cells after its label cell. The third row contains four blue rectangle cells after its label cell, and then one empty cell. There's 20 points of space between each of the cells.](Grid-4-iOS) The grid sets the width of all the cells in a column to match the needs of column's widest cell. In the example above, the width of the first column depends on the width of the widest ``Text`` view that the column contains. The other columns, which contain flexible ``Color`` views, share the remaining horizontal space offered by the grid's parent view equally. Similarly, the tallest cell in a row sets the height of the entire row. The cells in the first column of the grid above need only the height required for each string, but the ``Color`` cells expand to equally share the total height available to the grid. As a result, the color cells determine the row heights. ### Cell spacing and alignment You can control the spacing between cells in both the horizontal and vertical dimensions and set a default alignment for the content in all the grid cells when you initialize the grid using the ``init(alignment:horizontalSpacing:verticalSpacing:content:)`` initializer. Consider a modified version of the previous example: Grid(alignment: .bottom, horizontalSpacing: 1, verticalSpacing: 1) { // ... } This configuration causes all of the cells to use ``Alignment/bottom`` alignment --- which only affects the text cells because the colors fill their cells completely --- and it reduces the spacing between cells: ![A screenshot of a grid with three rows and six columns. The first column contains cells with the labels Row 1, Row 2, and Row 3, reading from top to bottom. The text is horizontally centered and bottom aligned in the cell in each case. The other columns contain cells that are either filled with a rectangle, or that are empty. Scanning from left to right, the first row contains two red rectangle cells after its label cell, and then three empty cells. The second row contains five green rectangle cells after its label cell. The third row contains four blue rectangle cells after its label cell, and then one empty cell. There's 1 point of space between each of the cells.](Grid-5-iOS) You can override the alignment of specific cells or groups of cells. For example, you can change the horizontal alignment of the cells in a column by adding the ``View/gridColumnAlignment(_:)`` modifier, or the vertical alignment of the cells in a row by configuring the row's ``GridRow/init(alignment:content:)`` initializer. You can also align a single cell with the ``View/gridCellAnchor(_:)`` modifier. ### Performance considerations A grid can size its rows and columns correctly because it renders all of its child views immediately. If your app exhibits poor performance when it first displays a large grid that appears inside a ``ScrollView``, consider switching to a ``LazyVGrid`` or ``LazyHGrid`` instead. Lazy grids render their cells when SwiftUI needs to display them, rather than all at once. This reduces the initial cost of displaying a large scrollable grid that's never fully visible, but also reduces the grid's ability to optimally lay out cells. Switch to a lazy grid only if profiling your code shows a worthwhile performance improvement.

Members (0)

This type has no directly callable members in this snapshot. See the framework’s skipped declarations for unsupported APIs.

Skipped declarations

1 declarations were excluded from these bindings. Each reason comes from the generator or the iOS SDK compiler.

Grid.init(alignment:horizontalSpacing:verticalSpacing:content:)

callback cannot propagate synchronous failure

All SwiftUI types →