Улучшите свой виджет

Попробуйте способ «Композиции»
Jetpack Compose — рекомендуемый набор инструментов для разработки пользовательского интерфейса для Android. Узнайте, как создавать виджеты с помощью API в стиле Compose.

На этой странице представлена информация о дополнительных улучшениях виджетов, доступных начиная с Android 12 (уровень API 31). Эти функции необязательны, но их легко реализовать и улучшить работу виджетов для пользователей.

Используйте динамические цвета

Начиная с Android 12, виджет может использовать цвета темы устройства для кнопок, фонов и других компонентов. Это обеспечивает более плавные переходы и единообразие между различными виджетами.

Существует два способа добиться динамических цветов:

  • Используйте тему системы по умолчанию ( @android:style/Theme.DeviceDefault.DayNight ) в корневом макете.

  • Используйте тему Material 3 ( Theme.Material3.DynamicColors.DayNight ) из библиотеки Material Components for Android , доступной начиная с Material Components for Android v1.6.0 .

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

Вот некоторые примеры атрибутов цвета, которые вы можете использовать:

  • ?attr/primary
  • ?attr/primaryContainer
  • ?attr/onPrimary
  • ?attr/onPrimaryContainer

В следующем примере с использованием темы Material 3 цвет темы устройства — «фиолетовый». Цвет акцента и фон виджета адаптируются для светлого и тёмного режимов, как показано на рисунках 1 и 2.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="?attr/colorPrimaryContainer"
  android:theme="@style/Theme.Material3.DynamicColors.DayNight">

  <ImageView
    ...
    app:tint="?attr/colorPrimaryContainer"
    android:src="@drawable/ic_partly_cloudy" />

    <!-- Other widget content. -->

</LinearLayout>
Виджет в светлой теме
Рисунок 1. Виджет в светлой теме.
Виджеты в темной теме
Рисунок 2. Виджет в тёмной теме.

Обратная совместимость для динамических цветов

Динамические цвета доступны только на устройствах под управлением Android 12 и более поздних версий. Чтобы создать собственную тему для более ранних версий, создайте тему по умолчанию с собственными цветами и новым квалификатором ( values-v31 ), используя атрибуты темы по умолчанию.

Вот пример использования темы Material 3:

/values/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="Theme.Material3.DynamicColors.DayNight">
    <!-- Override default colorBackground attribute with custom color. -->
    <item name="android:colorBackground">@color/my_background_color</item>

    <!-- Add other colors/attributes. -->

  </style>
</resources>

/values-v31/styles.xml

<resources>
  <!-- Do not override any color attribute. -->
  <style name="MyWidgetTheme" parent="Theme.Material3.DynamicColors.DayNight" />
</resources>

/layout/my_widget_layout.xml

<resources>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:background="?android:attr/colorBackground"
    android:theme="@style/MyWidgetTheme" />
</resources>

Включить голосовую поддержку

Действия приложения позволяют Google Ассистенту отображать виджеты в ответ на соответствующие голосовые команды пользователя. Настроив виджет на реакцию на встроенные намерения (BII) , ваше приложение сможет заблаговременно отображать виджеты на устройствах с Ассистентом, таких как Android и Android Auto. Пользователи могут закреплять виджеты, отображаемые Ассистентом, на панели запуска, чтобы стимулировать дальнейшее взаимодействие.

Например, вы можете настроить виджет сводки тренировки для своего приложения для тренировок так, чтобы он отвечал голосовым командам пользователя, запускающим функцию BII GET_EXERCISE_OBSERVATION . Помощник автоматически отображает ваш виджет, когда пользователи активируют эту функцию, выполняя запросы типа «Окей, Google, сколько миль я пробежал на этой неделе в ExampleApp?»

Существуют десятки BII, охватывающих различные категории пользовательского взаимодействия, что позволяет практически любому приложению Android улучшить свои виджеты для голосового управления. Чтобы начать работу, см. раздел Интеграция действий приложения с виджетами Android .

Улучшите возможности выбора виджетов в вашем приложении

Android 12 позволяет добавлять масштабированные превью виджетов и описания виджетов. Android 15 позволяет улучшить возможности выбора виджетов в вашем приложении с помощью сгенерированных превью виджетов.

Чтобы улучшить работу средства выбора виджетов в вашем приложении, предоставьте сгенерированный предварительный просмотр виджета на устройствах Android 15 и более поздних версий, масштабированный предварительный просмотр виджета (с указанием previewLayout ) для устройств Android 12 – Android 14 и previewImage для более ранних версий.

Добавить сгенерированные превью виджетов в средство выбора виджетов

Приложения должны установить значение compileSdk равным 35 или выше в файле build.gradle модуля, чтобы иметь возможность предоставлять RemoteViews модулю выбора виджетов на устройствах Android 15 и более поздних версиях. Это означает, что приложения могут обновлять содержимое в средстве выбора, чтобы оно лучше соответствовало тому, что видит пользователь.

Приложения могут использовать методы AppWidgetManager , setWidgetPreview и getWidgetPreview для обновления внешнего вида своих виджетов с использованием актуальной и персонализированной информации.

Создайте обновленный предварительный просмотр с помощью Jetpack Glance

Glance.compose запускает одну композицию, поэтому в теле вашего компонуемого объекта не используются функции приостановки, потоки или подобные асинхронные вызовы. Вместо этого необходимо использовать константные данные.

В следующем примере Jetpack Glance используется для создания обновлённого предварительного просмотра. Для отображения метода setWidgetPreview в этом фрагменте требуется настройка сборки compileSdk версии 35 или выше.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    ExampleAppWidget().compose(
        context = appContext
    ),
)

Создать обновленный предварительный просмотр без Jetpack Glance

Вы можете использовать RemoteViews без Glance. В следующем примере загружается XML-ресурс макета виджета и устанавливается в качестве предварительного просмотра. Для отображения метода setWidgetPreview в этом фрагменте требуется версия сборки compileSdk 35 или выше.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    RemoteViews("com.example", R.layout.widget_preview)
)

Добавить масштабируемые предварительные просмотры виджетов в средство выбора виджетов

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

Чтобы реализовать масштабируемые предварительные просмотры виджетов, используйте атрибут previewLayout элемента appwidget-provider для предоставления XML-макета:

<appwidget-provider
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>

Мы рекомендуем использовать тот же макет, что и у самого виджета, с реалистичными значениями по умолчанию или тестовыми значениями. Большинство приложений используют одни и те же previewLayout и initialLayout . Инструкции по созданию точных макетов для предварительного просмотра см. в следующем разделе на этой странице.

Мы рекомендуем указать оба атрибута: previewLayout и previewImage , чтобы ваше приложение могло использовать previewImage , если устройство пользователя не поддерживает previewLayout . Атрибут previewLayout имеет приоритет над атрибутом previewImage .

Рекомендуемые подходы для создания точных предварительных просмотров

Чтобы реализовать масштабируемые предварительные просмотры виджетов, используйте атрибут previewLayout элемента appwidget-provider для предоставления макета XML:

<appwidget-provider
    ...
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>
Изображение, показывающее предварительный просмотр виджета
Рисунок 3. Предварительный просмотр виджета, который по умолчанию отображается в области 3x3, но может поместиться в области 3x1 благодаря своему XML-макету.

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

  • Настройка android:text="@string/my_widget_item_fake_1" для элементов TextView .

  • Установка изображения или значка по умолчанию или заполнителя, например android:src="@drawable/my_widget_icon" , для компонентов ImageView .

Без значений по умолчанию предварительный просмотр может отображать неверные или пустые значения. Важным преимуществом такого подхода является возможность предоставления локализованного контента для предварительного просмотра.

Рекомендованные подходы для более сложных предварительных просмотров, содержащих ListView , GridView или StackView , см. в разделе Создание точных предварительных просмотров, включающих динамические элементы .

Обратная совместимость с масштабируемыми предварительными просмотрами виджетов

Чтобы разрешить средствам выбора виджетов на Android 11 (уровень API 30) или ниже отображать предварительный просмотр вашего виджета, укажите атрибут previewImage .

Если вы изменили внешний вид виджета, обновите изображение предварительного просмотра.

Добавьте имя к вашему виджету

Виджеты должны иметь уникальное имя при отображении в средстве выбора виджетов.

Имена виджетов загружаются из атрибута label элемента- receiver виджета в файле AndroidManifest.xml.

<receiver
    ….
   android:label="Memories">
     ….
</receiver>

Добавьте описание для вашего виджета

Начиная с Android 12, предоставьте описание для средства выбора виджетов, которое будет отображаться для вашего виджета.

Изображение, показывающее селектор виджетов, на котором показан виджет и его описание.
Рисунок 4. Пример выбора виджетов, показывающий виджет и его описание.

Введите описание для вашего виджета, используя атрибут description элемента &lt;appwidget-provider&gt; ;:

<appwidget-provider
    android:description="@string/my_widget_description">
</appwidget-provider>

Вы можете использовать атрибут descriptionRes в предыдущих версиях Android, но он игнорируется средством выбора виджетов.

Включить более плавные переходы

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

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

// Top-level layout of the widget.
<LinearLayout
    android:id="@android:id/background">
</LinearLayout>

Ваше приложение может использовать @android:id/background на предыдущих версиях Android без нарушения работы, но это будет игнорироваться.

Использовать модификацию RemoteViews во время выполнения

Начиная с Android 12, вы можете использовать несколько методов RemoteViews , которые позволяют изменять атрибуты RemoteViews во время выполнения. Полный список добавленных методов см. в справочнике по API RemoteViews .

В следующем примере кода показано, как использовать некоторые из этих методов.

Котлин

// Set the colors of a progress bar at runtime.
remoteView.setColorStateList(R.id.progress, "setProgressTintList", createProgressColorStateList())

// Specify exact sizes for margins.
remoteView.setViewLayoutMargin(R.id.text, RemoteViews.MARGIN_END, 8f, TypedValue.COMPLEX_UNIT_DP)

Ява

// Set the colors of a progress bar at runtime.
remoteView.setColorStateList(R.id.progress, "setProgressTintList", createProgressColorStateList());

// Specify exact sizes for margins.
remoteView.setViewLayoutMargin(R.id.text, RemoteViews.MARGIN_END, 8f, TypedValue.COMPLEX_UNIT_DP);