我們可以用可瀏覽的小組件填充鎖屏。實(shí)現(xiàn)鎖屏小組件很簡單,因?yàn)樗?API 與主屏小組件共享相同的代碼。本周我們將學(xué)習(xí)如何為我們的 App 實(shí)現(xiàn)鎖屏小組件。

iOS 呼聲最高的功能之一是可定制的鎖屏。終于,在最新發(fā)布的 iOS 16 得以實(shí)現(xiàn)。我們可以用可瀏覽的小組件填充鎖屏。實(shí)現(xiàn)鎖屏小組件很簡單,因?yàn)樗?API 與主屏小組件共享相同的代碼。本周我們將學(xué)習(xí)如何為我們的 App 實(shí)現(xiàn)鎖屏小組件。
讓我們從你可能早就有的 App 主屏小組件代碼開始。
struct WidgetView: View {
let entry: Entry
@Environment(\.widgetFamily) private var family
var body: some View {
switch family {
case .systemSmall:
SmallWidgetView(entry: entry)
case .systemMedium:
MediumWidgetView(entry: entry)
case .systemLarge, .systemExtraLarge:
LargeWidgetView(entry: entry)
default:
EmptyView()
}
}
}
在上面的示例中,我們有一個(gè)定義小組件的典型視圖。我們使用 Environment 來知道 widget family 并顯示適當(dāng)?shù)拇笮 N覀冃枰龅木褪莿h除默認(rèn)語句,并實(shí)現(xiàn)定義鎖屏小組件的所有新用例。
struct WidgetView: View {
let entry: Entry
@Environment(\.widgetFamily) private var family
var body: some View {
switch family {
case .systemSmall:
SmallWidgetView(entry: entry)
case .systemMedium:
MediumWidgetView(entry: entry)
case .systemLarge, .systemExtraLarge:
LargeWidgetView(entry: entry)
case .accessoryCircular:
Gauge(value: entry.goal) {
Text(verbatim: entry.label)
}
.gaugeStyle(.accessoryCircularCapacity)
case .accessoryInline:
Text(verbatim: entry.label)
case .accessoryRectangular:
VStack(alignment: .leading) {
Text(verbatim: entry.label)
Text(entry.date, format: .dateTime)
}
default:
EmptyView()
}
}
}
最好記住,系統(tǒng)對(duì)鎖屏和主屏小組件使用不同的渲染模式。系統(tǒng)為我們提供了三種不同的渲染模式。
- 主屏小組件和 Watch OS支持顏色的全色模式。是的,從 watchOS 9 開始,你還可以用 WidgetKit 去實(shí)現(xiàn) watchOS 的復(fù)雜性。
- 振動(dòng)模式(vibrant mode)是指系統(tǒng)將文本、圖像和儀表還原為單色,并為鎖屏背景正確著色。
- 重音模式(accented mode)僅在 watchOS 上使用,系統(tǒng)將小部件分為兩組,默認(rèn)和重音。 系統(tǒng)使用用戶在表盤設(shè)置中選擇的色調(diào)顏色為小部件的重音部分著色。
渲染模式可通過 SwiftUI Environment 變量使用,因此你可以始終檢查哪個(gè)渲染模式處于活動(dòng)狀態(tài),并將其反映在設(shè)計(jì)中。例如,可以使用具有不同渲染模式的不同圖片。
struct WidgetView: View {
let entry: Entry
@Environment(\.widgetRenderingMode) private var renderingMode
var body: some View {
switch renderingMode {
case .accented:
AccentedWidgetView(entry: entry)
case .fullColor:
FullColorWidgetView(entry: entry)
case .vibrant:
VibrantWidgetView(entry: entry)
default:
EmptyView()
}
}
}
如上所示,我們使用 widgetRenderingMode 環(huán)境值來獲得實(shí)際的渲染模式,并表現(xiàn)出不同的行為。像之前講到的,在重音模式( accented mode )下,系統(tǒng)將小部件分為兩部分,并對(duì)它們進(jìn)行特殊著色。可以使用 widgetAccentable 視圖修改器標(biāo)記視圖層次的一部分。在這種情況下,系統(tǒng)將知道哪些視圖應(yīng)用著色顏色。
struct AccentedWidgetView: View {
let entry: Entry
var body: some View {
HStack {
Image(systemName: "moon")
.widgetAccentable()
Text(verbatim: entry.label)
}
}
}
最后,我們需要為小組件配置支持類型。
@main
struct MyAppWidget: Widget {
let kind: String = "Widget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WidgetView(entry: entry)
}
.configurationDisplayName("My app widget")
.supportedFamilies(
[
.systemSmall,
.systemMedium,
.systemLarge,
.systemExtraLarge,
.accessoryInline,
.accessoryCircular,
.accessoryRectangular
]
)
}
}
如果你仍然支持 iOS 15,可以檢查新鎖屏小組件的可用性。
@main
struct MyAppWidget: Widget {
let kind: String = "Widget"
private var supportedFamilies: [WidgetFamily] {
if #available(iOSApplicationExtension 16.0, *) {
return [
.systemSmall,
.systemMedium,
.systemLarge,
.accessoryCircular,
.accessoryRectangular,
.accessoryInline
]
} else {
return [
.systemSmall,
.systemMedium,
.systemLarge
]
}
}
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WidgetView(entry: entry)
}
.configurationDisplayName("My app widget")
.supportedFamilies(supportedFamilies)
}
}