SwiftUI Grid 網格佈局教學

如果你想要製作像相簿、Instagram 個人頁面那樣的網格排版,LazyVGridLazyHGrid 是你的首選。

什麼是 LazyGrid?

"Lazy" (懶惰) 的意思跟 LazyHStack/LazyVStack 一樣,表示它只會建立即將顯示在螢幕上的 View。這對於包含大量圖片或資料的網格來說非常重要,能確保流暢的捲動體驗。

GridItem (網格項目設定)

在使用 Grid 之前,你需要先定義每一欄 (Column) 或每一列 (Row) 的佈局規則。這是透過 GridItem 來設定的。

GridItem 有三種尺寸模式:

  1. .fixed(size): 固定大小。
  2. .flexible(minimum, maximum): 彈性大小,會填滿剩餘空間 (最常用)。
  3. .adaptive(minimum, maximum): 自適應大小,盡可能放入越多項目越好。

LazyVGrid (垂直網格)

垂直網格需要定義「有幾欄 (Columns)」。

固定兩欄範例

let columns = [
    GridItem(.flexible()), // 第一欄彈性
    GridItem(.flexible())  // 第二欄彈性
]

ScrollView {
    LazyVGrid(columns: columns, spacing: 20) {
        ForEach(0..<20) { i in
            Rectangle()
                .fill(.orange)
                .aspectRatio(1, contentMode: .fit) // 保持正方形 1:1
                .overlay(Text("\(i)"))
        }
    }
    .padding()
}

自適應欄位 (Adaptive)

這是最強大的模式,它會根據螢幕寬度自動決定要顯示幾欄。例如,在手機上顯示 3 欄,在 iPad 上可能顯示 6 欄。

// 設定最小寬度為 100,盡可能塞入越多欄位
let adaptiveColumn = [
    GridItem(.adaptive(minimum: 100)) 
]

LazyVGrid(columns: adaptiveColumn) {
    // ... items
}

LazyHGrid (水平網格)

水平網格則需要定義「有幾列 (Rows)」。

let rows = [
    GridItem(.fixed(100)), // 第一列固定高度 100
    GridItem(.fixed(100))  // 第二列固定高度 100
]

ScrollView(.horizontal) {
    LazyHGrid(rows: rows) {
        // ... items
    }
}

Section (分區)

Grid 原生支援 Section 標頭 (Header) 和頁尾 (Footer),而且支援黏性標頭 (Sticky Header) 效果。

LazyVGrid(columns: columns, pinnedViews: [.sectionHeaders]) { // 開啟黏性標頭
    Section(header: Text("第一區").font(.title).background(.white)) {
        ForEach(0..<10) { i in
            Text("Item \(i)")
        }
    }
    
    Section(header: Text("第二區").font(.title).background(.white)) {
         ForEach(10..<20) { i in
            Text("Item \(i)")
        }
    }
}

透過 Grid,你可以輕鬆建立各種複雜且自適應的版面。