Виджеты уже давно являются важной частью возможностей Android, и многие приложения эффективно используют виджеты для повышения вовлеченности пользователей. Пользователи любят виджеты за возможность использовать функции приложения без его запуска и настраивать домашний экран своего устройства. В Android 12 обновлены существующие API виджетов и изменен дизайн виджетов в соответствии с языком дизайна "Material You". Эти изменения позволяют создавать более привлекательные виджеты, использующие цвета темы устройства и закругленные углы, а также улучшают открываемость и визуальные возможности поиска и размещения виджетов.

До изменений (Android 11) и после изменений со светлой и темной темой (Android 12)
До изменений (Android 11) и после изменений со светлой и темной темой (Android 12)

В этом цикле мини-статей мы рассмотрим обновление виджета для Android 12. В этой части мы рассмотрим несколько простых изменений, которые позволят вашему виджету отлично выглядеть на устройствах под управлением Android 12 и в то же время обеспечивать стабильную работу на более старых версиях Android. Во второй части мы рассмотрим новые API, которые сделают ваш виджет более персонализированным, отзывчивым и интерактивным.

Визуальные изменения

Неудивительно, что изменения стиля и дизайна являются наиболее заметными для пользователей. Обновление визуальных элементов, таких как цвета и радиус углов, мгновенно создает более свежий вид. Чтобы начать внедрение этих изменений, мы рекомендуем создать пользовательскую тему.

Добавьте динамические цвета

Material You нацелен на более персонализированный пользовательский опыт. В Android 12 динамические цвета позволяют вашему виджету смотреться более гармонично с другими виджетами и системой. Виджеты могут использовать тему системы по умолчанию Theme.DeviceDefault.DayNight и использовать атрибуты цвета темы в элементах пользовательского интерфейса виджета. Для этого необходимо создать пользовательскую тему из родительской DeviceDefault для версий ниже 31.

values/themes.xml

<style name="Theme.AppWidget.AppWidgetContainer" 
    parent="@android:style/Theme.DeviceDefault" />

Для версии 31 используйте родительскую тему DeviceDefault.DayNight для создания кастомной темы.

values-v31/themes.xml

<style name="Theme.AppWidget.AppWidgetContainer"  
    parent="@android:style/Theme.DeviceDefault.DayNight" />

В качестве альтернативы, если ваше приложение использует компоненты материала, вы можете использовать Theme.MaterialComponents.DayNight для базовой темы вместо Theme.DeviceDefault.

Чтобы ваш виджет динамически использовал системные цвета, назначьте эту тему своему виджету и используйте атрибуты цвета темы в других view.

layout/widget_checkbox_list_title_region.xml
...
<TextView android:id="@+id/checkbox_list_title"
    android:layout_width="0dp"
    android:layout_height="wrap_content"     
    android:layout_gravity="center_vertical" 
    android:layout_marginStart="8dp" 
    android:layout_weight="1" 
    android:text="@string/grocery_list" 
    android:textColor="?android:attr/textColorPrimary" />
<ImageButton
    android:layout_width="@dimen/widget_element_min_length"
    android:layout_height="@dimen/widget_element_min_length"
    android:background="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:contentDescription="@string/add_button_grocery_list_content_description"
    android:src="@drawable/ic_add_24"
    android:tint="?android:attr/colorAccent" />
...
Статические цвета против динамических цветов в светлой / темной теме
Статические цвета против динамических цветов в светлой / темной теме

Закругленные углы

Начиная с Android 12, закругленные углы автоматически применяются к виджетам. Это означает, что содержимое виджета может быть обрезано примененной маскировкой углов. Чтобы избежать этого и обеспечить более согласованный внешний вид и взаимодействие с другими виджетами и системой, вы можете использовать system_app_widget_background_radius для добавления закругленных углов контура виджета и system_app_widget_inner_radius для добавления закругленных углов внутри виджета. Это значение должно быть на 8dp меньше, чем system_app_widget_background_radius.

При этом следует помнить, что если ваш виджет имеет содержимое, расположенное близко к углам, это содержимое может быть обрезано. Чтобы исправить это, необходимо добавить достаточный паддинг, чтобы избежать перекрытия содержимого виджета с закругленными углами.

values/attrs.xml

<declare-styleable name="AppWidgetAttrs">
    <attr name="appWidgetPadding" format="dimension" />    
    <attr name="appWidgetInnerRadius" format="dimension" />
    <attr name="appWidgetRadius" format="dimension" />
</declare-styleable>


values/themes.xml

<style name="Theme.AppWidget.AppWidgetContainerParent" 
    parent="@android:style/Theme.DeviceDefault">
    <!-- Radius of the outer bound of widgets to make the rounded   
        corners -->
    <item name="appWidgetRadius">16dp</item>
    <!-- Radius of the inner view's bound of widgets to make the rounded corners. It needs to be 8dp or less than the value of appWidgetRadius -->
    <item name="appWidgetInnerRadius">8dp</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainer" 
    parent="Theme.AppWidget.AppWidgetContainerParent">
    <!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
    <item name="appWidgetPadding">16dp</item>
</style>


values-v31/themes.xml

<style name="Theme.AppWidget.AppWidgetContainerParent" 
    parent="@android:style/Theme.DeviceDefault.DayNight"> 
    <item name="appWidgetRadius">
        @android:dimen/system_app_widget_background_radius</item>      
    <item name="appWidgetInnerRadius">
        @android:dimen/system_app_widget_inner_radius</item>
</style>


values/styles.xml

<style name="Widget.AppWidget.AppWidget.Container" 
    parent="android:Widget">
    <item name="android:id">@android:id/background</item>
    <item name="android:background">
        ?android:attr/colorBackground</item>
</style>

Если ваш minTargetSDK ниже версии 21, вам необходимо предоставить стили для версии 21, поскольку android:attr/colorBackground, используемый в чертежах, требует уровня API 21.

Теперь, создавая тему, вы можете установить стиль для layout-a виджета.

layout/widget_grocery_list.xml

<LinearLayout
    style="@style/Widget.AppWidget.AppWidget.Container">
    ...
</LinearLayout>
Как было раньше и автоматическая маскировка углов против закругленных углов и примененных отступов
Как было раньше и автоматическая маскировка углов против закругленных углов и примененных отступов

Переходы

Android 12 предлагает улучшенные переходы при запуске приложения из виджета. Этот переход обрабатывается системой автоматически и не будет отображаться на старых версиях Android. Чтобы включить его, необходимо указать id и установить его значение в android:id/background на корневом элементе макета виджета.

<LinearLayout
    android:id="@android:id/background">
    ...
</LinearLayout>
Замедленный переход
Замедленный переход

Если ваш виджет использует broadcast trampolines, что означает, что ваш виджет создает PendingIntent по клику пользователя, чтобы запустить событие из броадкаста или сервиса, эта анимация не будет использоваться.

Новые улучшения предпросмотра виджетов

Превью

В Android 12 есть новый улучшенный инструмент выбора виджетов. Вместо использования статичного ресурса drawable, новый виджет-пикер использует XML-layout для динамического создания масштабированного предварительного просмотра вашего виджета. Если ваш виджет не содержит динамических элементов, таких как ListView или GridView, вы можете просто использовать layout виджета для предварительного просмотра. Чтобы это работало, необходимо установить значения по умолчанию непосредственно в исходный макет.

<TextView
    style="@style/Widget.AppWidget.Checkbox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/widget_title_preview" />
<TextView
    style="@style/Widget.AppWidget.Checkbox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/widget_subject_preview" />

Установка значений по умолчанию в макете может вызвать небольшую задержку, когда фейковые значение отображается до того, как будет применено реальное значение. Чтобы избежать этого, можно создать отдельный файл макета для предварительного просмотра и применить кастомную тему предварительного просмотра.

<resources>
    <!-- Declare attributes -->
    <attr name="widgetTitlePreview" format="string" />
    <attr name="widgetSubjectPreview" format="string" />
    <!-- Declare styles -->
    <style name="Theme.MyApp.Widget" 
        parent="@style/Theme.DeviceDefault.DayNight.AppWidget">
        <item name="widgetTitlePreview"></item>
        <item name="widgetSubjectPreview"></item>
    </style>
    <style name="Theme.MyApp.Widget.Preview">
        <item name="widgetTitlePreview">Preview Title</item>
        <item name="widgetSubjectPreview">Preview Subject</item>
    </style>
</resources>

Когда у вас есть тема предварительного просмотра, вы можете применить ее к элементу предварительного просмотра в layout.

layout/my_widget_preview.xml

<LinearLayout ...>
    <include layout="@layout/widget_header"
         android:theme=”@style/Theme.MyApp.Widget.Preview” /></LinearLayout>


layout/my_widget_actual.xml

<LinearLayout ...>
    <include layout="@layout/widget_header"
        android:theme=”@style/Theme.MyApp.Widget” />
</LinearLayout>

Наконец, вам нужно настроить layout виджета, чтобы он был указан в качестве атрибута previewLayout для appwidget-provider.

xml/app_widget_info_checkbox_list.xml

<appwidget-provider
    android:previewLayout="@layout/widget_grocery_list"
    ... 
/>
Статический предварительный просмотр и предварительный просмотр с масштабированием
Статический предварительный просмотр и предварительный просмотр с масштабированием

Установка значений по умолчанию непосредственно на макете невозможна для нескольких элементов, отображаемых в ListView, GridView или Stack. В таких случаях можно создать другой layout для предварительного просмотра виджета и установить несколько жестко закодированных элементов в этом макете. При этом рекомендуется не дублировать весь layout, а использовать тег <include> для повторного использования тех частей макета, которые работают со значениями по умолчанию. Вы можете установить этот новый layout в качестве атрибута previewLayout в appwidget-provider.

Описание

Вы также можете установить атрибут description, чтобы предоставить описание, которое будет отображаться в виджет-пикере. Хотя это необязательно, предоставление описания может помочь пользователям лучше понять, что может делать ваш виджет.

app_widget_info_checkbox_list.xml

<appwidget-provider
   android:description="@string/app_widget_grocery_list_description"
   ... 
/>
Описание виджета
Описание виджета

Резюмируя

Это было не слишком сложно, не так ли? В этом посте вы увидели, как обновить дизайн виджета и предложить лучший пользовательский опыт в виджет-пикере. Это действительно просто, чтобы начать обновлять ваши виджеты для Android 12, и ваши пользователи сразу же заметят визуальную разницу. Но это еще не все. В следующей статье мы рассмотрим новые API, которые сделают ваши виджеты более персонализированными, более отзывчивыми и более интерактивными.

Оригинальная статья

Комментарии (2)


  1. quaer
    20.08.2021 10:03

    С углами разобрались, теперь их нельзя использовать для элементов управления, таких как "потяни за уголок".

    Но всё-таки ещё недоработки остались - чекбоксы по прежнему квадратные, поля ввода - прямоугольные. Хотя кнопки уже плохо заметны, они всё ещё тоже прямоугольные.

    Да и вообще, зачем все эти поля ввода и кнопочки? Всё должно вводиться через камеру и микрофон. Написал на салфетке, сфотографировал. Или сказал что надо, потом выслушиваешь ответ. Всё управление в программах должно быть свайпам, потряхиваниями, покручиваниями, 10-ти пальцевыми нажатиями. Причём обязательно настраиваемыми, чтобы никто не смог воспользоваться чужим устройством.


    1. apteem
      20.08.2021 13:29

      «чекбоксы по прежнему квадратные, поля ввода — прямоугольные. Хотя кнопки уже плохо заметны, они всё ещё тоже прямоугольные.» — у всего из этого углы уже с радиусом по умолчанию