Одной из самых востребованных функций для 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()
}
}
}
Напомню, что система использует разные режимы рендеринга для виджетов экрана блокировки и домашнего экрана. Система предоставляет нам три разных режима рендеринга.
- Полноцветный режим для виджетов главного экрана и расширений watchOS с поддержкой цветов. И да, вы также можете использовать WidgetKit для реализации расширений watchOS, начиная с watchOS 9.
- В ярком режиме система обесцвечивает текст, изображения и датчики, превращая их в монохромные, и окрашивает их подходяще для фона экрана блокировки.
- Акцентный режим используется только в 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()
}
}
}
Как вы можете видеть в приведенном выше примере, мы используем значение среды widgetRenderingMode, чтобы получить фактический режим рендеринга и изменить виджет. Как я уже говорил, в акцентированном режиме система делит ваш виджет на части и раскрашивает их особым образом. Вы можете пометить часть вашей иерархии представлений с помощью модификатора представления widgetAccentable. В этом случае система будет знать, какие представления будут использовать цвет оттенка.
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. И вы можете легко в коде виджета получить значения среды, чтобы понять, какой режим рендеринга активен в данный момент.
Еще
- Создание виджетов экрана блокировки и расширений часов
- Отличия Live Screen Widgets и Live Activities:

