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

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

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

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

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

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

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

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

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

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

В следующем примере с темой «Материал 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 Assistant отображать виджеты в ответ на соответствующие голосовые команды пользователя. Настроив виджет так, чтобы он реагировал на встроенные намерения (BII) , ваше приложение может активно отображать виджеты на поверхностях Ассистента, таких как Android и Android Auto. Пользователи имеют возможность закреплять виджеты, отображаемые Ассистентом, на своей панели запуска, поощряя дальнейшее взаимодействие.

Например, вы можете настроить виджет сводки тренировок для своего приложения для тренировок так, чтобы он выполнял голосовые команды пользователя, которые запускают GET_EXERCISE_OBSERVATION BII. Ассистент заранее отображает ваш виджет, когда пользователи запускают этот BII, отправляя запросы типа: «Эй, 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);