使用 SwiftUI 为 iOS16 实现锁屏小组件
· 阅读需 5 分钟
iOS 要求最多的功能之一是可定制的锁屏。最后,我们在最新的iOS 16上得到了它。我们可以用一目了然的小组件填充我们的 锁屏。实现锁屏小组件很简单,因为它的API与主屏幕小组件共享相同的代码。下面我们将学习如何为我们的应用程序实现锁屏小组件。
让我们从应用程序中可能已有的用于显示主屏幕小组件的代码开始。
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()
}
}
}
在上面的示例中,我们有一个定义小组件的典型视图。我们使用环境来了解小组件系列,并显示适当大小的视图。为了支持锁屏小组件,我们只需要删除默认语句,并实现所有定义锁屏小组件的新情况。
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()
}
}
}
最好记住,系统对锁屏和主屏幕小组件使用不同的渲染模式。该系统为我们提供了三种不同的渲染模式。
- 主屏幕小组件的 Full-color 模式和支持颜色的watchOS复杂功能。是的,您也可以使用WidgetKit实现watchOS复杂功能,从watchOS 9开始。
- Vibrant 模式是系统将文本、图像和仪表分解为单色,并为锁屏背景正确着色。
- Accented 模式仅在 watchOS上使用,系统将小组件分为两组,默认和重音。系统会用用户在表盘设置中选择的色调颜色为小组件的重音部分着色。
渲染模式可以通过 SwiftUI 环境获得,因此您可以随时检查哪种渲染模式处于活动状态,并将其反映在您的设计中。例如,您可以使用具有不同渲染模式的不同图像。
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()
}
}
}
如上例所示,我们使用小组件渲染模式环境值来获取实际渲染模式并做出不同的行为。正如我之前所说,在重音模式下,系统将您的小组件分为两部分,并专门为它们着色。您可以使用小组件可重音视图修饰符标记视图层次结构的一部分。在这种情况下,系统将知道哪些视图应用色调颜色。
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)
}
}
今天,我们学习了如何在iOS 16中实现新的锁屏小组件。请记住,我们可以重用相同的API来构建watchOS复杂功能。您可以通过查看环境值来轻松共享小组件代码库,以了解当前哪种渲染模式处于活动状态。