在現今最流行的 App中,例如 Facebook、Instagram 和 Twitter,你不難發現它們都使用標籤介面。 這種介面在App底部會出現一個標籤欄,讓使用者可以在不同功能之間快速切換。 如使用 UIKit ,您可以利用UITabBarController
來建立標籤欄界面。 SwiftUI 框架則提供了一個名為TabView
的 UI 組件,供開發者在App製作標籤介面。
在本章中,我們將向你解構 TabView
並建立標籤欄界面、處理標籤選擇以及自訂標籤欄的外觀。
假設您已經使用 Xcode 開啟了一個 SwiftUI 項目,讓我們從一個簡單的Text
視圖開始,如下所示:
struct ContentView: View {
var body: some View {
Text("Home Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
}
}
要將這個文字視圖嵌入到標籤欄中,你只需要利用 TabView
組件包裝它就可以。而通過附加 .tabItem
修飾器,你就可以設置標籤項的描述,如下所示:
struct ContentView: View {
var body: some View {
TabView {
Text("Home Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
}
}
}
這就建立了一個帶有選項的標籤列。 在範例程式碼中,選項同時具有圖像和文字,但您可以隨意刪除其中之一。
要顯示更多選項,您只需在 TabView
中添加子視圖,如下所示:
TabView {
Text("Home Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
Text("Bookmark Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("Bookmark")
}
Text("Video Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "video.circle.fill")
Text("Video")
}
Text("Profile Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "person.crop.circle")
Text("Profile")
}
}
這就建立了一個帶有 4 個選項的標籤列。
在預設的情況下,標籤列項目的顏色是設置為藍色。 您可以通過將 .tint
修飾器附加到 TabView
來更改其顏色,如下所示:
TabView {
}
.tint(.red)
如果您將以上程式碼加到TabView
,標籤列的顏色就會更改為白色。
標籤視圖會自動處理使用者的選擇,當使用者點擊其中一個項目標籤視圖就會切換至相關項目視圖。 在某些情況,您可能希望以寫程式方式切換到特定選項。 TabView
有另一個用於此目的的 init
方法。 該方法需要一個包含選項卡標籤值的狀態變數:
TabView(selection: $selection)
舉例,在 ContentView 中宣告以下狀態變數:
@State private var selection = 0
這裡我們將 selection
變數的原始值設定為0
,這是第一個選項的標籤值。 我們還沒有為每個選項定義標籤值。 因此,像這樣更新程式碼並為每個選項附加 tag
修飾器:
TabView(selection: $selection) {
Text("Home Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(0)
Text("Bookmark Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("Bookmark")
}
.tag(1)
Text("Video Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "video.circle.fill")
Text("Video")
}
.tag(2)
Text("Profile Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "person.crop.circle")
Text("Profile")
}
.tag(3)
}
我們透過附加 tag
修飾器為每個選項提供唯一索引。 TabView
也綁定到 selection
值。 要以編程方式切換到指定選項,就只需要更新 selection
變數的值。
您可以建立一個 Next 按鈕來切換至下一個選項,如下所示:
ZStack(alignment: .topTrailing) {
TabView(selection: $selection) {
.
.
.
}
.tint(.red)
Button {
selection = (selection + 1) % 4
} label: {
Text("Next")
.font(.system(.headline, design: .rounded))
.padding()
.foregroundStyle(.white)
.background(.red)
.cornerRadius(10.0)
.padding()
}
}
進行修改後,在預覽中運行App,您可以點擊 Next 按鈕跳至不同選項。
你可以通過以下程式碼利用 NavigationStack
包裹 TabView
組件將標籤視圖嵌入導航視圖中:
NavigationStack {
TabView(selection: $selection) {
.
.
.
}
.navigationTitle("TabView Demo")
}
在 UIKit 中,還有一個名為 hidesBottomBarWhenPushed
的選項,它允許您在使用導航界時自動隱藏標籤欄。 SwiftUI 也內置了此功能。 您可以像這樣修改程式碼:
NavigationStack {
TabView(selection: $selection) {
List(1...10, id: \.self) { index in
NavigationLink(
destination: Text("Item #\(index) Details"),
label: {
Text("Item #\(index)")
.font(.system(size: 20, weight: .bold, design: .rounded))
})
}
.listStyle(.plain)
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(0)
Text("Bookmark Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("Bookmark")
}
.tag(1)
Text("Video Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "video.circle.fill")
Text("Video")
}
.tag(2)
Text("Profile Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
.tabItem {
Image(systemName: "person.crop.circle")
Text("Profile")
}
.tag(3)
}
.tint(.red)
.navigationTitle("TabView Demo")
}
我們只是更改了 Home 選項卡的程式碼以顯示項目列表。 我們用NavigationLink
包裝每個列表項目,以便在選擇該項時導航至詳細信息視圖。 如果您使用模擬器或在預覽中運行App,當導航到詳細信息視圖時,標籤欄就會自動隱藏。
就某些情況,您可能不希望隱藏選標籤欄。 如果是這個樣的話,您可以反過來建立導航界面。 不是將標籤視圖包裝在導航視圖中,而是將導航視圖嵌入到標籤視圖中,如下所示:
TabView(selection: $selection) {
NavigationStack {
List(1...10, id: \.self) { index in
NavigationLink(
destination: Text("Item #\(index) Details"),
label: {
Text("Item #\(index)")
.font(.system(size: 20, weight: .bold, design: .rounded))
})
}
.navigationTitle("TabView Demo")
}
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(0)
.
.
.
}
現在,當您導航到項目的詳細信息視圖時,標籤欄仍然存在。
在本章中,我們向您介紹了 TabView
的基礎知識,它是 SwiftUI 中用於建立標籤介面的 UI 組件。 SwiftUI框架沒有為您提供許多用於自訂標籤欄的選項。 但是,您仍然可依賴 UIKit 的 API 來自訂其外觀。
在本章所準備的範例檔中,有最後完整的 Xcode 專案,可供你下載參考:
https://www.appcoda.com/resources/swiftui5/SwiftUITabView.zip