iOS 17 App 程式設計實戰心法(SwiftUI)

第 21 章
使用標籤視圖及自訂標籤列

If you're trying to achieve, there will be roadblocks. I've had them; everybody has had them. But obstacles don't have to stop you. If you run into a wall, don't turn around and give up. Figure out how to climb it, go through it, or work around it.

- Michael Jordan

「標籤列」( Tab Bar )是在螢幕底部的一列持續可見的按鈕,其作為開啟App 不同功能的導覽元件,儘管它曾經被認為在主流 UI 設計中不突出,但標籤列最近又重新流行起來。

在大螢幕裝置出現之前,只有 3.5 吋及 4 吋規格的 iPhone,而使用標籤列的一個缺點是它們占用寶貴的螢幕空間,這對於小螢幕來說,尤其具有挑戰性。然而,在 2014 年底推出大螢幕尺寸的iPhone 6 及iPhone 6 Plus 之後,App 開發者開始用標籤列取代現有的選單。著名的 App 如 Facebook、Whatsapp、Twitter、Quora、Instagram 及 Apple Music,都轉向了標籤列導覽。

標籤列的優點是允許使用者只要點擊一下,即可訪問 App 的核心功能,儘管它們占用了螢幕空間,但權衡之下被認為是值得的。

導覽控制器藉由管理一堆視圖控制器來幫助分層內容導覽,而標籤列管理多個不一定具有直接關係的視圖控制器。通常標籤列控制器至少包含二個標籤,你可按照 App 的需求增加最多五個標籤。

圖 21.1. 為 FoodPin App 新增標籤列
圖 21.1. 為 FoodPin App 新增標籤列

我在上一章中介紹過 TabView,但是我們將它設定為頁面滾動視圖。在本章中,我們將使用它來建立一個如圖21.1 所示的標準標籤介面。我們將建立具有三個項目的標籤列:

  • Favorites - 這是餐廳清單畫面。
  • Discover - 這是一個發掘由你的朋友或世界各地的其他美食愛好者所推薦的最愛餐廳畫 面。我們將在 iCloud 一章中實作這個標籤。
  • About - 這是 App的「關於」畫面,這裡我們先留下空白,到下一章中再來進行。 最重要的是,我們將教你如何在 SwiftUI 中自訂標籤列。

使用 TabView 建立標籤介面

在開發導引視圖時,我們將 TabView 設定為使用 PageTabViewStyle,如下所示:

TabView {
  .
  .
  .
}
.tabViewStyle(.page(indexDisplayMode: .always))

這將建立一個允許使用者可在不同頁面之間導覽的頁面滾動視圖。要建立標準標籤視圖,只需省略 .tabViewStyle 修飾器並使用預設樣式。以下是一個例子:

TabView {
   Text("Discover")
       .tabItem {
           Label("Discover", systemImage: "wand.and.rays")
       }
       .tag(1)

   Text("About")
       .tabItem {
           Label("About", systemImage: "square.stack")
       }
       .tag(2)
}

上列的程式碼建立了一個標準標籤介面,其中一個標籤列顯示兩個標籤項目。

對於我們的 FoodPin 專案,我們將建立一個單獨檔案來存放標籤介面。在專案導覽器中的「View」資料夾上按右鍵,並選擇「New File...」,然後選取「SwiftUI View」模板, 將檔案命名為「MainView.swift」。

在 MainView 結構中,宣告一個狀態變數來存放目前的標籤索引:

@State private var selectedTabIndex = 0

然後更新 body 視圖如下:

TabView(selection: $selectedTabIndex) {
    RestaurantListView()
        .tabItem {
            Label("Favorites", systemImage: "tag.fill")
        }
        .tag(0)

    Text("Discover")
        .tabItem {
            Label("Discover", systemImage: "wand.and.rays")
        }
        .tag(1)

    Text("About")
        .tabItem {
            Label("About", systemImage: "square.stack")
        }
        .tag(2)
}

我們在標籤視圖中有三個標籤,第一個標籤是 RestaurantListView,而其他兩個標籤是 Text 視圖。要建立標籤列UI,我們將三個子視圖包裹在一個 TabView 中,對於每個視圖,我們使用 tabItem 修飾器來指定名稱與圖片。系統圖片是來自於內建的 SF Symbols。

在接下來的章節中,我們會實作 Discover 與 About 視圖,現在我們將它們保持為一個簡單的文字視圖。進行這些更改後,在預覽窗格中執行 App,你應該能夠與標籤列進行互動,如圖 21.2 所示。

圖 21.2. 在標籤介面中嵌入餐廳清單視圖
圖 21.2. 在標籤介面中嵌入餐廳清單視圖

調整標籤列項目的顏色

動作標籤項目的顏色是黑色,這是因為我們沒有為標籤視圖指定主色。要變更動作標籤列項目的顏色,則將 .tint 修飾器加到 TabView:

.tint(Color("NavigationBarTitle"))

嘗試再次測試 App,當你導覽到細節視圖時,標籤列現在應該會消失,如圖 21.3 所示。

圖 21.3. 自訂標籤列項目的顏色
圖 21.3. 自訂標籤列項目的顏色

設定初始視圖

假設你已經正確實作所有的程式碼更改,你應該能夠在預覽窗格中預覽 MainView。然而,如果你在模擬器中執行 App,則只會載入 RestaurantListView,因為它被設定為 App 的初始視圖。

要更改它的話,開啟 FoodPinApp.swift 並更新body 如下:

var body: some Scene {
    WindowGroup {
        MainView()
    }
    .modelContainer(for: Restaurant.self)
}

這是你設定 App 的初始視圖的地方。當你將 RestaurantListView 更改為 MainView,再次於任何模擬器上執行這個App,App 應該會載入 MainView 而不是 RestaurantListView 了。

本章小結

到目前為止,你應該充分了解如何建立基於標籤列的使用者介面,並加入新的標籤列項目。如你所見,SwiftUI 簡化了在標籤視圖中嵌入視圖的過程,使其實現起來非常簡單。

使用 SwiftUI,您可以彈性地自訂標籤視圖的外觀和行為,進而打造具有吸引力且直覺的使用者介面。無論你是想顯示 App 的不同功能、呈現分層內容、還是提供對基本功能的快速訪問,SwiftUI 的標籤視圖都提供了方便且有效率的解決方案。

透過利用至目前為止所介紹的觀念與技術,您將具備在SwiftUI App 中實作基於標籤的導覽的所需知識及工具,為使用者提供無縫且愉快的體驗。

在本章所準備的範例檔中,有最後完整的Xcode 專案可供你下載參考:http://www.appcoda.com/resources/swift59/swiftui-foodpin-tabview.zip