SwiftUI 框架

Xcode 14.3 新功能:輕鬆客製化 SwiftUI Bottom Sheet 背景及滾動行為

iOS 16 推出後,要在 SwiftUI 建立一個互動式 bottom sheet 十分輕鬆,我們只需要在 Sheet 視圖嵌入一個 presentationDetents 修飾符就可以了。在這篇文章中,讓我帶大家客製化自己的 Bottom Sheet。
Xcode 14.3 新功能:輕鬆客製化 SwiftUI Bottom Sheet 背景及滾動行為
Photo by CardMapr.nl on Unsplash
Xcode 14.3 新功能:輕鬆客製化 SwiftUI Bottom Sheet 背景及滾動行為
Photo by CardMapr.nl on Unsplash
In: SwiftUI 框架

iOS 16 推出後,我們可以輕鬆在 SwiftUI 建立一個互動式 (interactive) bottom sheet。我們只需要在 Sheet 視圖嵌入一個 presentationDetents 修飾符就可以了。之前,我們曾經發佈過一篇詳細的教學去介紹這個 API。不過,大家可能已經忘了如何使用這個 API,所以先讓我們看看以下的範例程式碼:

struct BasicBottomSheet: View {
    @State private var showSheet = false
 
    var body: some View {
        VStack {
            Button("Show Bottom Sheet") {
                showSheet.toggle()
            }
            .buttonStyle(.borderedProminent)
            .sheet(isPresented: $showSheet) {
                Text("This is the expandable bottom sheet.")
                    .presentationDetents([.medium, .large])
            }
 
            Spacer()
        }
    }
}

我們利用 sheet 修飾符來建立一個 presentation sheet,然後,在 sheet 裡面插入 presentationDetents 修飾符來控制 sheet 的大小。.medium.height 都是內建的 detent。

除了可以調整 sheet 的高度之外,我們沒有什麼可以客製化的。不過,隨著 iOS 16.4 推出,我們有了更多可以客製化的選項,像是建立客製化背景、控制 sheet 的滾動等等。

讓我們看看 presentation sheet 有甚麼客製化的選項吧!請注意,你需要使用 Xcode 14.3(或以上版本),才可以跟著這篇教學進行實作。

客製化 SwiftUI Bottom Sheet 的背景

現在有了新的 presentationBackground 修飾符,我們就可以這樣改變 sheet 的背景顏色:

.presentationBackground(.yellow)

我們也可以應用背景的 material type,來為 sheet 創建模糊效果:

struct ContentView: View {
    @State private var showSheet = false
    
    var body: some View {
        ZStack(alignment: .top) {
            Image("wallpaper")
                .resizable()
                .scaledToFill()
                .clipped()
                .ignoresSafeArea()
            
            Button("Show Bottom Sheet") {
                showSheet.toggle()
            }
            .tint(.black)
            .buttonStyle(.borderedProminent)
            .sheet(isPresented: $showSheet) {
                Text("This is the expandable bottom sheet.")
                    .presentationDetents([ .medium, .large])
                    .presentationBackground(.thinMaterial)
                    
            }
        }
    }
}

如果我們把 presentation 背景設置為 .thinMaterial,就可以在 sheet 和背景圖像之間添加一個半透明層。

swiftui-bottom-sheet-thinmaterial

或者,我們也可以這樣使用修飾符,來把客製化視圖設置為 sheet 的背景:

.presentationBackground {
    Image("wallpaper")
}

客製化 Presentation Sheet 的 Corner Radius

這次的更新還有一個新的修飾符 presentationCornerRadius,讓我們可以調整 presentation sheet 的 corner radius。讓我們看看以下例子:

swiftui-bottom-sheet-cornerradius

啟用與背景視圖互動

在之前的 iOS 版本,SwiftUI 會禁用 bottom sheet 後面的視圖,如此一來,使用者就需要先關閉 sheet,才可以與背景視圖互動。從 iOS 16.4 開始,SwiftUI 引入了另一個修飾符 presentationBackgroundInteraction,讓開發者可以選擇啟用或禁用互動。

要啟用背景視圖互動,我們可以把 presentationBackgroundInteraction 修飾符附加到 sheet 視圖,並把值設置為 .enabled

.presentationBackgroundInteraction(.enabled)

在這個情況下,使用者就可以與 sheet 後面的視圖互動了。

swiftui-sheet-background-interaction

我們也可以利用 detent 限制背景視圖互動。例如,bottom sheet 有 3 個不同的 intent:

.presentationDetents([ .height(100), .medium, .large])

如果我們只想使用者與某個 intent 的背景視圖互動,我們可以這樣設置 presentationBackgroundInteraction 修飾符:

.presentationBackgroundInteraction(.enabled(upThrough: .height(100)))

定義滾動行為

在預設情況下,如果 bottom sheet 中包含滾動視圖,當使用者在滾動視圖向上滑動時,sheet 就會擴展到下一個 detent。如果你不明白我的意思,我們可以來看看另一個例子。

假設我們這樣在 bottom sheet 顯示了一個項目列表:

.sheet(isPresented: $showSheet) {
    List(1...20, id: \.self) { index in
        Text("Item \(index)")
    }
    .presentationDetents([.medium, .large])
}

當我們開啟一個 bottom sheet 時,它會被帶到 medium detent。但是,我們無法滾動列表。當我們想在滾動視圖向上滑動時,sheet 就會擴展到全螢幕。

如果想讓使用者在 sheet 半打開的狀態下滾動列表,我們可以嵌入 presentationContentInteraction 修飾符,並將其值設置為 .scrolls

.sheet(isPresented: $showSheet) {
    List(1...20, id: \.self) { index in
        Text("Item \(index)")
    }
    .presentationDetents([.medium, .large])
    .presentationContentInteraction(.scrolls)
}

如此一來,即使 sheet 是半打開的狀態,使用者都可以向上或向下滾動列表:

swiftui-scrollable-sheet

使用者也可以按住並拖動 drag indicator,來調整 sheet 的大小。

先睹為快

在編寫這篇文章時,Apple 仍在測試 iOS 16.4 的 Beta 版,但預計很快就會正式推出。如果你想試試最新的 SwiftUI 更新,必定要下載 Xcode 14.3 (beta)。

譯者簡介:Kelly Chan-AppCoda 編輯小姐。
作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 17 App 程式設計實戰心法》、《iOS 17 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。