LazyVGrid in SwiftUI

LazyVGrid in SwiftUI is a layout view that arranges its child views in a vertical grid, loading items on-demand for improved performance. This layout is especially useful when displaying a large amount of data, as it loads each cell only as it’s about to appear on-screen, saving memory and enhancing scrolling performance.

Key Properties

  • columns: Defines the number, size, and spacing of columns in the grid.
  • spacing: Sets the spacing between items in the grid.
  • alignment: Controls the horizontal alignment of each item in the grid.

Basic Usage

Here’s how to set up a LazyVGrid with flexible columns:

import SwiftUI

struct ContentView: View {
    let items = Array(1...50)  // Sample data

    // Define flexible columns with 3 equal-width items per row
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]

    var body: some View {
        ScrollView {  // Add ScrollView to make the grid scrollable
            LazyVGrid(columns: columns, spacing: 16) {
                ForEach(items, id: \.self) { item in
                    Text("Item \(item)")
                        .frame(width: 80, height: 80)
                        .background(Color.blue)
                        .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}

Defining Grid Columns

LazyVGrid allows flexible configuration of columns using GridItem, which provides options for defining column widths and spacing:

  1. .flexible(): Columns adjust their width to fill available space. Great for responsive layouts.
  2. .fixed(width): Fixed-width columns that do not adjust to screen size.
  3. .adaptive(minimum: width): Columns automatically adjust to fit as many items as possible, given a minimum width.

Example of Adaptive Columns

let adaptiveColumns = [
    GridItem(.adaptive(minimum: 80))  // Minimum width of 80 for each item
]

With .adaptive, items will fill as many columns as they can, based on available space, resulting in a responsive grid that adjusts to different screen sizes. Here is the full example:

import SwiftUI

struct ContentView: View {
    let items = Array(1...50)  // Sample data
    
    
    let adaptiveColumns = [
        GridItem(.adaptive(minimum: 80))  // Minimum width of 80 for each item
    ]
    
    
    var body: some View {
        ScrollView {  // Add ScrollView to make the grid scrollable
            LazyVGrid(columns: adaptiveColumns, spacing: 16) {
                ForEach(items, id: \.self) { item in
                    Text("Item \(item)")
                        .frame(width: 80, height: 80)
                        .background(Color.blue)
                        .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}

fixed() size modifier

If we want to create a LazyVGrid with fixed-sized columns, we can use the .fixedSize() modifier for each column. Here’s an example of how to create a LazyVGrid with fixed columns:

import SwiftUI

struct ContentView: View {
    let items = Array(1...50)  // Sample data
    
    // Define fixed columns with 3 equal-width items per row
    let columns = [
        GridItem(.fixed(100)),
        GridItem(.fixed(100)),
        GridItem(.fixed(100))
    ]
    
    var body: some View {
        ScrollView {  // Add ScrollView to make the grid scrollable
            LazyVGrid(columns: columns, spacing: 16) {
                ForEach(items, id: \.self) { item in
                    Text("Item \(item)")
                        .frame(width: 80, height: 80)
                        .background(Color.blue)
                        .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}

Customizing Item Layout and Appearance

You can customize each item’s appearance by setting background colors, frames, and corner radius within the grid.

ForEach(items, id: \.self) { item in
    Text("Item \(item)")
        .frame(maxWidth: .infinity, minHeight: 80)
        .background(Color.orange.opacity(0.6))
        .cornerRadius(12)
}

Example: Building a Photo Grid

Here’s a common use case for LazyVGrid: a photo gallery app layout.

import SwiftUI

struct ContentView: View {
    let photoURLs: [String] = [
        "https://picsum.photos/600",
        "https://picsum.photos/500",
        "https://picsum.photos/700",
        "https://picsum.photos/800",
        "https://picsum.photos/id/42/600",
        "https://picsum.photos/id/43/600",
    ]
    let columns = [
        GridItem(.adaptive(minimum: 100))  // Minimum width 100 for each image
    ]
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 10) {
                ForEach(photoURLs, id: \.self) { url in
                    AsyncImage(url: URL(string: url)) { image in
                        image
                            .resizable()
                            .scaledToFill()
                    } placeholder: {
                        ProgressView()
                    }
                    .frame(width: 100, height: 100)
                    .clipped()
                    .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}

Benefits of Using LazyVGrid

  1. Performance: Only visible items are loaded, making it efficient for large datasets.
  2. Flexible Layouts: Allows responsive grids with a variety of item arrangements.
  3. Memory Efficient: Reduces memory footprint by loading items on-demand.

Using LazyVGrid makes it easy to create dynamic, high-performance grids suitable for photo galleries, dashboards, and many other apps with grid-based layouts.

Leave a Reply