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

На этой странице приведены сведения о дополнительных улучшениях виджетов, которые доступны, начиная с 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>

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

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

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

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

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

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

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

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

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

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

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

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

В следующем примере 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);