Программирование
Создаем виджеты для экрана блокировки на SwiftUI
Мы можем заполнить наш экран блокировки красивыми виджетами. Реализовать виджет для экрана блокировки несложно, поскольку его API использует тот же код, что и виджеты домашнего экрана.
Одной из самых востребованных функций для 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: