SwiftUI offers two new views LazyVGrid
and LazyHGrid
to show views in a grid layout that expands either vertically or horizontally. The word Lazy means that the grid view does not create items until they are needed. Thous views are available from iOS 14 and upward.
Here are the steps to create a grid layout.
First, prepare the raw data to present in the grid.
var colors: [Color] = [.orange, .green, .gray]
Next, create an array of GridItem
that describes how the grid looks like. Here is a sample code snippet for describing a 2-column grid:
var grid = [GridItem(.flexible()), GridItem(.flexible())]
Finally, layout the grid by using LazyVGrid
and ScrollView
.
ScrollView { LazyVGrid(columns: threeColumnGrid) { // Display the item } }
You use GridItem
instances to configure the layout of items in LazyHGrid
and LazyVGrid
views. Grid item is either row or column.
GridItems
are declared using the following syntax
GridItem(sizing, spacing, alignment)
We have three options to specify the size of the grid item
flexible(minimum: CGFloat, maximum: CGFloat)
specifies single flexible item in available space with optional parameters for min and max size.adaptive(minimum: CGFloat, maximum: CGFloat)
specifies the size of the row or column is adjusted to fit as many items as possible into the available space.fixed(CGFloat)
specifies a single item with a fixed size in available space.Flexible
A flexible grid item lets you specify a range of sizes while still defining the number of columns. We can provide minimum and maximum, but it works great even without that. The item size is calculated by dividing available space by item count.
struct ContentView: View { private var colors: [Color] = [.orange, .green, .gray] private var items = [GridItem(.flexible(minimum: 60)), GridItem(.flexible()), GridItem(.flexible())] struct ItemView: View { var index: Int var color: Color var body: some View { Text("\(index)") .frame(minWidth: 50, maxWidth: .infinity, minHeight: 100) .background(color) .cornerRadius(4) } } var body: some View { ScrollView { LazyVGrid(columns: items, spacing: 4) { ForEach((0...10), id: \.self) { index in ItemView(index: index, color: colors[index % colors.count]) } } .padding(4) } } }
Adaptive
Adaptive grid layout size is the most suitable and appropriate GridItem
size. It fills the space with as many columns or rows as fit in the grid. To use adaptive sizing, modify the items
array to contain a single adaptive item as follows:
private var items = [GridItem(.adaptive(minimum: 80))]
This change will result in the grid displaying as many columns as possible with the restriction that the column width cannot be less than 80dp.
Fixed
Fixed grid layout size allows rows or columns to be set at a specific size. When using only fixed GridItems
in the array passed to the grid view, the number of GridItems
will set the number of rows or columns. For example, the following array, when passed to a LazyVGrid
view, will display a grid containing a single column with a width of 80dp.
private var items = [GridItem(.fixed(80))]
On the other hand, the following array will display a three column grid with the columns sized at 30dp, 40dp and 50dp respectively:
private var items = [GridItem(.fixed(30)), GridItem(.fixed(40)), GridItem(.fixed(50))]
When working with grids it is also possible to combine GridItem
sizing configurations. For example, the following array, , will display the first column of each row with a fixed width with the second and third columns sized equally to occupy the remaining space:
private var items = [GridItem(.fixed(30)), GridItem(), GridItem()]
Using the LazyHGrid View
Horizontal grids work in much the same way as vertically oriented grids with the exception that the configuration is based on rows instead of columns, and that the fixed, minimum and maximum values relate to row height instead of column width.
struct ContentView: View { private var colors: [Color] = [.orange, .green, .gray] private var items = [GridItem(.adaptive(minimum: 40))] struct ItemView: View { var index: Int var color: Color var body: some View { Text("\(index)") .frame(minWidth: 50, minHeight: 50, maxHeight: .infinity) .background(color) .cornerRadius(4) } } var body: some View { ScrollView(.horizontal) { LazyHGrid(rows: items, spacing: 4) { ForEach((0...50), id: \.self) { index in ItemView(index: index, color: colors[index % colors.count]) } } .padding(4) } } }