SwiftUI 框架

如何使用SwiftUI Grid API 創建網格佈局

SwiftUI 4.0 引入了一個新的 Grid API 來組成基於網格的佈局。 你可以使用 VStack 和 HStack 安排相同的佈局。 然而,Grid 視圖使其變得容易得多。
如何使用SwiftUI Grid API 創建網格佈局
如何使用SwiftUI Grid API 創建網格佈局
In: SwiftUI 框架

SwiftUI 4.0 引入了一個新的 Grid API 來組成基於網格的佈局。 你可以使用 VStackHStack 安排相同的佈局。 然而,Grid 視圖使其變得容易得多。 Grid 視圖是一種容器視圖,它以二維佈局排列其他視圖。

讓我們從一個簡單的網格開始。 要創建一個 2x2 網格,你可以編寫如下程式碼:

struct ContentView: View {
    var body: some View {
        Grid {
            GridRow {
                Color.purple
                Color.orange
            }
            
            GridRow {
                Color.green
                Color.yellow
            }
        }
    }
}

假設你已經在 Xcode 中創建了一個 SwiftUI 項目,你應該會看到一個 2x2 的網格,其中填上了不同的顏色。

swiftui-grid-api

要建立 3x3 網格,你只需添加另一個 GridRow。 並且,對於每個GridRow,再插入一個子視圖。

比較網格視圖和堆棧視圖

為什麼我們需要使用 Grid API? 我們其實可以使用 HStackVStack創建相同的網格 UI。 那麼,蘋果為什麼要引入這個新的 API? 對!你可以使用堆棧視圖構建相同的網格。 然而,有一個主要的區別使得 Grid 視圖在構建網格佈局時更受歡迎。

讓我們使用下面的程式碼創建另一個 2x2 網格:

struct ContentView: View {
    var body: some View {
        Grid {
            GridRow {
                Image(systemName: "trash")
                    .font(.system(size: 100))
                Image(systemName: "trash")
                    .font(.system(size: 50))
            }
            
            GridRow {
                Color.green
                Color.yellow
            }
        }
    }
}

這次,第一行顯示兩個系統圖像,第二行顯示彩色視圖。 你的預覽應顯示如下所示的網格。

swiftui-grid-api-vstack-hstack

要使用嵌套的VStackHStack構建相同的網格佈局,我們可以編寫如下程式碼:

VStack {
    HStack {
        Image(systemName: "trash")
            .font(.system(size: 100))
            .frame(minWidth: 0, maxWidth: .infinity)
        Image(systemName: "trash")
            .font(.system(size: 50))
            .frame(minWidth: 0, maxWidth: .infinity)
    }
    
    HStack {
        Color.green
        Color.yellow
    }
}

在預設的情況下,Grid 視圖的每一列在一行中佔據相等的空間。 但對於 HStack,我們必須附加 frame 修飾器以使每張圖像在行中佔據相同的空間。

Grid 視圖只是讓創建網格視圖變得更容易,並提供了幾個修改器來自定義網格佈局。

使用 gridCellColumns 合併單元格

創建網格視圖時,你可能希望在特定行中顯示單個單元格,而其他行繼續顯示多個單元格。 gridCellColumns 修飾器專為你合併單元格而設計。 這是一個例子:

Grid {
    GridRow {
        Image(systemName: "trash")
            .font(.system(size: 100))
        Image(systemName: "trash")
            .font(.system(size: 50))
    }
    
    GridRow {
        Color.purple
            .overlay {
                Image(systemName: "magazine.fill")
                    .font(.system(size: 100))
                    .foregroundColor(.white)
            }
            .gridCellColumns(2)
    }
}

第二行只有一個單元格。 我們附加 gridCellColumn 修飾器並將其值設置為 2 以合併單元格。 如果你不使用修飾器,就會看到一個空白單元格。

添加空白單元格

swiftui-3x3-grid

現在讓我們像這樣創建另一個 3x3 網格視圖:

struct ContentView: View {
    var body: some View {
        Grid {
            GridRow {
                IconView(name: "cloud")
                IconView(name: "cloud")
                IconView(name: "cloud")
            }
            
            GridRow {
                IconView(name: "cloud")
                IconView(name: "cloud")
                IconView(name: "cloud")
            }
            
            GridRow {
                IconView(name: "cloud")
                IconView(name: "cloud")
                IconView(name: "cloud")
            }
        }
    }
}

struct IconView: View {
    var name: String = "trash"
    
    var body: some View {
        Image(systemName: name)
            .frame(width: 100, height: 100)
            .background(in: Rectangle())
            .backgroundStyle(.purple)
            .foregroundStyle(.white.shadow(.drop(radius: 1, y: 3.0)))
            .font(.system(size: 50))
    }
}

如果我們想為網格中心的單元格顯示一個空白視圖怎麼辦? 為此,你可以使用以下程式碼添加一個空白單元格:

Color.clear
    .gridCellUnsizedAxes([.horizontal, .vertical])

如果用上面的程式碼替換中心單元格,你將在網格中心看到一個空白單元格。

gridCellUnsizedAxes 修飾器可防止空白單元格佔用的空間超過行或列中其他單元格所需的空間。 如果省略修飾器,就會出現如圖 7 所示的網格佈局。

調整單元格間距

要控制單元格之間的垂直和水平間距,你可以在建立 Grid 視圖時使用 horizontalSpacingverticalSpacing 參數:

Grid(horizontalSpacing: 0, verticalSpacing: 0) {
  .
  .
  .
}

如果需要在行之間添加一些間距,可以將 padding 修飾器附加到 GridRow。 下圖是一個示例:

控制單元對齊

Grid 視圖有一個名為 alignment 的參數,供你配置單元格的預設對齊方式。 例如,此處將對齊方式設置為 .bottom :

Grid(alignment: .bottom, horizontalSpacing: 0, verticalSpacing: 0) {
  .
  .
  .
}

如果你更改了程式碼,黑框應與單元格底部就會對齊。

要更改預設對齊設置,單元格本身可以附加 gridCellAnchor 修飾器來更改對齊方式。 下圖是一個例子:

總結

Grid API 為開發人員提供了構建基於網格的佈局的更多選項。 你可以使用HStackVStack來構建類似的佈局。 但是 Grid 視圖可以為你節省大量代碼並使你的程式碼更具可讀性。 如果你的App只需要支持最新版本的 iOS,可以嘗試使用 Grid API 來構建一些有趣的佈局。


💡
此文摘自《精通 SwiftUI》一書。
作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 18 App 程式設計實戰心法》、《iOS 18 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何在 SwiftUI App 中開發 Live Activities
SwiftUI 框架

如何在 SwiftUI App 中開發 Live Activities

Live Activities 首次於 iOS 16 推出,是 Apple 最令人興奮的更新之一,能讓 App 與使用者在即時互動上更有連結。它不再需要使用者不斷打開 App,Live Activities 可以讓資訊直接顯示在鎖定畫面和 Dynamic Island 上。
使用 Tool Calling 強化 Foundation Models 功能
AI

使用 Tool Calling 強化 Foundation Models 功能

在前幾篇教學中,我們介紹了 Foundation Models 在 iOS 26 中的運作方式,以及如何使用這個全新框架打造具備 AI 功能的應用。我們也介紹了 @Generable 巨集,它能輕鬆地將模型回應轉換為結構化的 Swift 類型。 現在,在這個 Foundation
活用 Foundation Models 的 @Generable 與 @Guide 製作測驗 App
AI

活用 Foundation Models 的 @Generable 與 @Guide 製作測驗 App

在前一篇教學中,我們介紹了 Foundation Models 框架,並示範了如何用它來進行基本的內容生成。那個過程相當簡單——你提供一個提示詞(prompt),等幾秒鐘,就能獲得自然語言的回應。在我們的範例中,我們建立了一個簡單的問答 App,讓使用者可以提問,App 則直接顯示生成的文字。 但如果回應變得更複雜——你需要把非結構化文字轉換為結構化的物件呢? 舉例來說,
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。