輕鬆地在 iOS 15 創建 Bottom Sheet:UISheetPresentationController  


隨著 SwiftUI 推出,有些人會問 UIKit 會否被淘汰。答案是:當然還沒有要被淘汰。在 iOS 15 中,Apple 的工程師繼續為 UIKit 推出新功能,其中一個亮點就是 UISheetPresentationController。這個新類別讓我們只需幾行程式碼,就可以輕鬆創建可擴展的 Bottom Sheet。

如果你不知道什麼是 Bottom Sheet,你可以打開內置的 Maps App 看看。App 會顯示一個 Bottom Sheet,讓使用者執行搜尋和存取保存的位置。Sheet 的大小可以調整,我們也可以拖動 Bottom Sheet 來展開或折疊它。事實上,這種 UI 模式在其他受歡迎的 App 中都很常見,像是 Google Maps、Twitter 和 Instagram。

bottom-sheet-apple-maps

在這篇教學文章中,我們會看看如何使用 UISheetPresentationController,並客製化其屬性 (property)。這次的範例 App 非常簡單,只有一個按鈕,點掣按鈕後,App 就會利用 Bottom Sheet 顯示 Web 內容。

利用 UISheetPresentationController 來顯示一個 Bottom Sheet

在 iOS 15 中,UIViewController 有一個名為 sheetPresentationController 的新屬性。對於繼承自 UIViewController 的視圖控制器,我們可以存取其 sheetPresentationController 屬性來檢索 UISheetPresentationController 的實例,以客製化其外觀。

我們可以設置 detents 屬性,來指定 sheetPresentationController 的大小。讓我們看看以下範例,了解一下如何設置 Bottom Sheet 的大小。

let webViewController = WebViewController()

if let sheet = webViewController.sheetPresentationController {
    sheet.detents = [ .medium(), .large() ]
}

present(webViewController, animated: true)

WebViewController 類別是 UIViewController 的子類別,因此我們可以從 sheetPresentationController 屬性中檢索 UISheetPresentationController 的實例。

detents 屬性是用來指定 Sheet 的高度陣列。我們可以使用 .medium() 來讓 Sheet 佔據螢幕的一半。如果要以 full height 顯示 Sheet,就可以使用 .large() detent。

bottom-sheet-medium-large-size

以上的範例程式碼分別使用了 .medium().large() detents 屬性。在這種情況下,Sheet 會先佔據螢幕的一半。當我們向上拖動 Web 視圖控制器時,Sheet 就會完全展開。

如果你如此改變值的次序,App 就會先以 full height 顯示 Sheet。

sheet.detents = [ .large(), .medium() ]

客製化 Bottom Sheet 來添加 Grabber

除了控制 Sheet 的大小之外,UISheetPresentationController 類別還提供了許多可以客製化的選項。

UISheetPresentationController-grabber

比如說,如果我們想在 Sheet 的頂部顯示一個 Grabber,就可以把 prefersGrabberVisible 屬性設為 true

sheet.prefersGrabberVisible = true

在顯示 Bottom Sheet 的時候,底層的視圖會自動變暗。如果我們想保持底層視圖的光度,可以把 smallestUndimmedDetentIdentifier 的值設置為 .medium

sheet.smallestUndimmedDetentIdentifier = .medium

如此一來,在顯示 Bottom Sheet 時,系統就不會把底層的視圖變暗。

為滾動視圖 (Scroll View) 客製化 Bottom Sheet

如果我們使用 .medium() 尺寸的 Sheet 來顯示可滾動內容,就可能會遇到一個問題。在我們向上滾動內容時,Sheet 也會被展開,這並不是我們想要的效果。我們希望在滾動內容時,Sheet 的大小可以保持不變。

bottom-sheet-scrolling-view

UISheetPresentationController 有一個名為 prefersScrollingExpandsWhenScrolledToEdge 的屬性,就可以解決這個問題了。我們只需要把屬性的值設置為 false

sheet.prefersScrollingExpandsWhenScrolledToEdge = false

設置好之後,即使 Sheet 只佔螢幕的一半,我們都可以正常地滾動內容。要展開 Bottom Sheet,就可以向上拖動 Grabber。

prefersScrollingExpandsWhenScrolledToEdge-demo

客製化圓角半徑 (Corner Radius)

bottom-sheet-corner-radius

我們可以利用 preferredCornerRadius 屬性,來改變 bottom sheet 的圓角半徑,數值越大,邊角就越圓。

sheet.preferredCornerRadius = 30.0

總結

UIKit 新增的類別 UISheetPresentationController 非常有用,我們不再需要自己實作來顯示 bottom sheet,很簡單就可以在 App 上使用這個漂亮的手機 UI Pattern。

譯者簡介:Kelly Chan-AppCoda 編輯小姐。
原文Displaying a Bottom Sheet in iOS 15 Using UISheetPresentationController


軟件工程師,AppCoda 創辦人。著有《iOS 13 App 程式設計實力超進化實戰攻略》、《iOS 13 App 程式設計實力超進化實戰攻略》以及《精通 SwiftUI》。曾任職於HSBC, FedEx等公司,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda,致力於iOS程式教學,產品設計及開發。

blog comments powered by Disqus
Shares
Share This