Mastering the Grid in SwiftUI

Fireworks, habr. Before we move on to the article, I want to share with you absolutely free of charge a recording of two very useful lessons that our teachers gave in anticipation of the start of basic and advanced courses on iOS development:

  1. A quick start to iOS development
  2. Making a multi-threaded Kotlin Multiplatform application

Now let’s move on to the article.


This week I want to talk to you about Grids, one of the most anticipated new features in SwiftUI. Everyone was looking forward to an alternative UICollectionView in SwiftUI, and finally it came out this year. SwiftUI provides us with views LazyVGrid and LazyHGridwhich we can use to create layouts with grids of elements.

The basics

LazyVGrid and LazyHGrid Are two new View types that SwiftUI provides us to create a super custom Layout based on a grid of items. The only difference between them is the fill axis. LazyVGrid fills the available space in a vertical direction. LazyHGrid it places its children horizontally. The axis is the only difference between these two views. That’s why everything you learn about LazyVGrid, applicable to LazyHGrid and vice versa. Let’s take a look at the first example.

struct ContentView: View {
    private var columns: [GridItem] = [
        GridItem(.fixed(100), spacing: 16),
        GridItem(.fixed(100), spacing: 16),
        GridItem(.fixed(100), spacing: 16)
    ]

    var body: some View {
        ScrollView {
            LazyVGrid(
                columns: columns,
                alignment: .center,
                spacing: 16,
                pinnedViews: [.sectionHeaders, .sectionFooters]
            ) {
                Section(header: Text("Section 1").font(.title)) {
                    ForEach(0...10, id: .self) { index in
                        Color.random
                    }
                }

                Section(header: Text("Section 2").font(.title)) {
                    ForEach(11...20, id: .self) { index in
                        Color.random
                    }
                }
            }
        }
    }
}

In the above example, we are creating a three column grid where each column is a fixed size of 100pt. I’m going to use this example to describe all the configuration options available to us.

  1. Parameter columns Is an array that defines the columns in the grid layout. To describe a column, SwiftUI provides us with the type GridItem… We’ll talk about it a little later.
  2. Parameter alignment allows us to align the contents of the grid using an enum HorizontalAlignment for LazyVGrid and VerticalAlignment for LazyHGrid… Works the same as stack alignment
  3. Parameter spacing indicates the distance between each line inside LazyVGrid or space between each column inside LazyHGrid
  4. Parameter pinnedViews allows you to define options for pinning section headers and footers (headers and footers). It is empty by default, which means that headers and footers behave like content and disappear on scrolling. You can enable pinning of the header and footer, in which case they will overlap with the content and become permanently visible.

GridItem

Each column in the grid must be defined with a structure GridItem… A type GridItem allows us to specify size, alignment, and spacing for each column. Let’s take a look at a small example.

private var columns: [GridItem] = [
    GridItem(.fixed(50), spacing: 16, alignment: .leading),
    GridItem(.fixed(75)),
    GridItem(.fixed(100))
]

As you can see, each column can have different size, spacing, and alignment options. The most interesting thing here is the size. There are three ways to determine the size of a column within a grid. It can be fixed, flexible, or adaptive.

Fixed the column is the most obvious. The grid places the column according to the size you specify. In the previous example, we created a three-column layout in which the columns are fixed at 50pt, 75pt, and 100pt, respectively.

Option flexible allows you to define a column that expands or contracts based on the available space. We can also provide minimum and maximum flexible column sizes. By default it uses a minimum value of 10pt and is not capped at the maximum.

private var columns: [GridItem] = [
    GridItem(.flexible(minimum: 250)),
    GridItem(.flexible())
]

Here we create a layout that divides the available space between two flexible columns. The first column takes up 250pt of its minimum size, while the second has all the rest of the available space.

The most interesting option is adaptive… The responsive option allows us to place multiple elements in the space of a single flexible column. Let’s try to figure it out with an example.

private var columns: [GridItem] = [
    GridItem(.adaptive(minimum: 50, maximum: 100)),
    GridItem(.adaptive(minimum: 150))
]

As you can see, we have two responsive columns. The first column contains several elements with a minimum size of 50pt and a maximum of 100pt. Responsive columns are useful when the number of items within a column needs to be based on the available space.
The real power of grids is when you start mixing column types. You can create a two-column layout, where the first is fixed and the second is responsive. Let’s see how it will look.

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

Conclusion

The grid allows you to create very complex and interesting layouts by mixing different types GridItem… It should be noted that all changes to the meshes can be animated. I hope you enjoyed this article. Feel free to follow me at Twitter and ask your own questions related to this topic. Thank you for your attention, see you!


You can find out more about our courses using the links below:


Similar Posts

Leave a Reply