[iOS] 16.1 Live Activities (即時動態) 快速上手教學 (下)
iOS 16.1 Live Activities(即時動態) 之動態島
上一篇我們提到了即時動態的基本應用和相關的設定,那這篇我們就來聊聊更多關於即時動態能做到的酷炫功能吧!
上次我們提到關於 ActivityConfiguration 的設置:
import SwiftUI import WidgetKit @available(iOSApplicationExtension 16.1, *) @main struct PizzaDeliveryWidget: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in // 製作鎖定畫面應該顯示的畫面,這也同時支援沒有動態島的iOS裝置。 } dynamicIsland: { context in // 製作動態島顯示畫面,這部分下一章會再細說 // ... } } }
但也只有針對上半部 context 的設計去作延伸,但我相新眼尖的各位一定有發現在 closure 的下面有另外一個 context 的設定,看字面上的意思,當然就是關於動態島的設置,因為這部分的內容偏多、複雜,所以我就另外寫一篇文章來跟大家分享。
Dynamic Island 動態島
首先呢,以開發者的角度來看的話,Apple 官方在開發動態島的元件 UI 時,有列出了一些規範和不同的顯示狀況:
一. 當使用者只有一個顯示中的即時動態時,動態島會在畫面上呈現 Leading side (頭) 跟 Trailing side (尾)。
二. 當使用者同時有不只一個即時動態在運作的時候,兩個即時動態會以 minimal 的方式在 UI 上做互動,動態島選擇一個優先級別更高的顯示在 Leading side,而另一個會以圓形圖示展現在 trailing side 的位置。
- Center:位於相機組件下方,由於區域不大,所以建議放置 static data(靜態 data)。
- Leading:為左半邊 L 型區塊,範圍較大能夠放圖像或是比較明顯的資訊。
- Trailing:為右半邊反 L 型區塊,跟 Leading 的可用範圍基本一樣。
- Bottom:下方到底的區塊,這邊的範圍比較規矩,因此能過做更多動態的調整,不管是 animation 或是動態文字都是不錯的選擇。
但如果你不需要這麼多區塊怎麼辦呢?
有些人可能只想要 Leading + Trailing 的話,這樣 Center 跟 Bottom 不就會卡在那個地方影響整體畫面嗎?
這個問題 Apple 官方也給出的相對應的方法去達到不同的要求,init(_:priority:content:) 能夠調整整個動態島在擴張之後區塊渲染的先後順序,因此就能達到特定區塊長滿的需求:
如此一來,開發者就有更多可以應用的空間,不管今天是怎樣的互動性 App 都能依照自己的風格去定義屬於自己的即時動態。
程式碼實作
照著上次建立過的 ActivityConfiguration 繼續往下擴展的話:
import SwiftUI import WidgetKit @available(iOSApplicationExtension 16.1, *) @main struct PizzaDeliveryWidget: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in // 製作鎖定畫面應該顯示的畫面,這也同時支援沒有動態島的iOS裝置。 } dynamicIsland: { context in // 製作動態島應該顯示的畫面 DynamicIsland { //MARK: -文章上方提到的(三). DynamicIslandExpandedRegion(.leading) { Label("(context.attributes.numberOfPizzas) Pizzas", systemImage: "bag") .foregroundColor(.indigo) .font(.title2) } DynamicIslandExpandedRegion(.trailing) { Label { Text(timerInterval: context.state.deliveryTimer, countsDown: true) .multilineTextAlignment(.trailing) .frame(width: 50) .monospacedDigit() } icon: { Image(systemName: "timer") .foregroundColor(.indigo) } .font(.title2) } DynamicIslandExpandedRegion(.center) { Text("(context.state.driverName) is on their way!") .lineLimit(1) .font(.caption) } DynamicIslandExpandedRegion(.bottom) { Button { // Deep link into your app. } label: { Label("Call driver", systemImage: "phone") } .foregroundColor(.indigo) } //MARK: -文章提到的(一) } compactLeading: { // Create the compact leading presentation. // ... } compactTrailing: { // Create the compact trailing presentation. // ... //MARK: -文章提到的(二) } minimal: { // Create the minimal presentation. // ... } .keylineTint(.yellow) } } }
以官方範例來操作的話,可以看到我們文章提到的一、二、三都有被實作在裡面,每個區域都一一列出,但如果有些區域不設定的話,他就不會有任何操作反應。
如果 build & run 之後,應該可以看到在你的動態島被 request 完建立後,在有動態島的機子上就會看到你的動態島會有下面的幾種畫面:
那如果需要設定 priority 的話,假設你只要 Leading 跟 Trailing,則 Center 跟 Bottom 就不需要設定:
import SwiftUI import WidgetKit @available(iOSApplicationExtension 16.1, *) @main struct PizzaDeliveryWidget: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in // 製作鎖定畫面應該顯示的畫面,這也同時支援沒有動態島的iOS裝置。 } dynamicIsland: { context in // 製作動態島應該顯示的畫面 DynamicIsland { //MARK: -文章上方提到的(三). DynamicIslandExpandedRegion(.leading, priority: 1) { //自訂畫面 } //MARK: -文章提到的(一) } compactLeading: { // Create the compact leading presentation. // ... } compactTrailing: { // Create the compact trailing presentation. // ... //MARK: -文章提到的(二) } minimal: { // Create the minimal presentation. // ... } .keylineTint(.yellow) } } }
應該有人發現在 Dynamic Island closure的下方有一行.keylineTint(.yellow)這行的作用就是可以決定動態島的邊框顏色,沒錯!這個設置真的很棒,這樣就可以依照每個 App 自己的主題色去做設置!
這樣基本上你就完成一個有動態島支援的即時動態啦!
以上就是這篇文章的內容,那因為公司隱私的問題,我還是沒辦法把自己實作的程式碼放上來,還請大家多多包涵,如果有任何問題歡迎到我的IG私訊我,或在底下留言告訴我喔~謝謝!
如果想給我一些支持,也歡迎買杯咖啡給我,謝謝大家!
留言
張貼留言