创建简单的 widget

尝试使用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何使用 Compose 样式的 API 构建 widget。

应用 widget 是可以嵌入其他应用(如主屏幕)并接收定期更新的微型应用视图。这些视图称为界面中的 widget,您可以使用应用 widget 提供程序(或 widget 提供程序)发布 widget。能够容纳其他 widget 的应用组件称为应用 widget 托管应用(或 widget 托管应用)。 图 1 显示了一个示例音乐 widget:

音乐 widget 示例
图 1.音乐 widget 示例。

本文档介绍如何使用 widget 提供程序发布 widget。如需 详细了解如何创建自己的 AppWidgetHost 来托管 应用 widget,请参阅构建 widget 托管应用

如需了解如何设计 widget,请参阅应用 widget 概览

widget 组件

如需创建 widget,您需要以下基本组件:

AppWidgetProviderInfo 对象
描述 widget 的元数据,如 widget 的布局、更新频率和 AppWidgetProvider 类。AppWidgetProviderInfoXML 中定义,如本文档中所述。
AppWidgetProvider
定义允许您以编程方式与 widget 连接的基本方法。通过它,您会在更新、启用、停用或删除 widget 时收到广播。您可以在清单中声明 AppWidgetProvider,然后 实现它,如本文档中所述。
查看布局
定义 widget 的初始布局。布局在 XML 中 定义,如本文档中所述。

图 2 显示了这些组件如何融入整体应用 widget 处理流程。

应用 widget 处理流程
图 2.应用 widget 处理流程。

如果您的 widget 需要用户配置,请实现应用 widget 配置 activity。此 activity 可让用户修改 widget 设置,例如时钟 widget 的时区。

  • 从 Android 12(API 级别 31)开始,您可以提供默认配置,并让用户稍后重新配置 widget。如需了解详情,请参阅使用 widget 的默认配置允许用户重新配置已放置的 widget
  • 在 Android 11(API 级别 30)或更低版本中,每当用户将 widget 添加到其主屏幕时,系统都会启动此 activity。

我们还建议进行以下改进:灵活的 widget 布局其他增强功能高级 widget集合 widget构建 widget 托管应用

声明 AppWidgetProviderInfo XML

在传统视图和基于 Glance 的 widget 中,定义元数据设置(例如默认单元格大小、调整大小限制和更新频率)的方式完全相同。

如需了解如何定义和配置元数据 XML 文件,请参阅 Glance 文档中的“Compose-first ”声明 AppWidgetProviderInfo XML 部分

使用 AppWidgetProvider 类处理 widget 广播

平台的广播接收器机制、清单声明过滤器和生命周期事件循环在平台下统一。在 Compose-first 开发中,这些广播使用 GlanceAppWidgetReceiver 封装容器进行编排。

如需了解如何在清单中注册接收器并实现 与 Hilt 兼容的生命周期替换,请参阅 Glance 文档中的“Compose-first”使用 AppWidgetProvider 类处理广播部分

创建 widget 布局

您必须在 XML 中定义 widget 的初始布局,并将其保存在项目的 res/layout/ 目录中。如需了解详情,请参阅设计准则

如果您熟悉 布局,则创建 widget 布局非常简单。不过,请注意,widget 布局基于 RemoteViews,后者不支持每种布局或视图 widget。 您无法使用自定义视图或 RemoteViews 支持的视图的子类。

RemoteViews 还支持 ViewStub,它是一个大小为零的不可见 View,您可以使用它在运行时以懒散的方式扩充布局资源。

支持有状态行为

Android 12 使用以下现有组件新增了对有状态行为的支持:

widget 仍然无状态。您的应用必须存储状态并注册状态更改事件。

显示有状态行为的购物清单 widget 示例
图 3.有状态行为示例。

以下代码示例展示了如何实现这些组件。

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

提供两个布局:一个面向搭载 Android 12 或 更高版本的设备(位于 res/layout-v31 中),另一个面向之前的 Android 11 或更低版本(位于默认 res/layout 文件夹中)。

实现圆角

计算外部背景和内部比例半径是标准且共享的。在 Compose-first 开发中,这可以在 Kotlin 中与自定义主题资源一起动态设置。

如需为旧版 Android 设备实现圆角半径或设置动态样式, 请参阅 Glance 文档中的“Compose-first”实现圆角部分