以下部分介绍如何使用 Glance 创建基本应用微件。
在清单中声明 AppWidget
完成 设置步骤后,在应用中声明 AppWidget 及其
元数据。
从
GlanceAppWidgetReceiver扩展AppWidget接收器:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
在
AndroidManifest.xml文件和关联的元数据文件中注册应用微件的提供程序:<receiver android:name=".glance.MyReceiver" android:exported="true"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/my_app_widget_info" /> </receiver>
添加 AppWidgetProviderInfo 元数据
接下来,按照创建微件指南中的说明在 @xml/my_app_widget_info 文件中创建和定义应用
微件信息。
Glance 的唯一区别在于没有 initialLayout XML,但您必须定义一个。您可以使用库中提供的预定义加载布局:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
声明 AppWidgetProviderInfo XML
AppWidgetProviderInfo 对象定义了微件的基本特性。在 XML 元数据资源文件
(res/xml/my_app_widget_info.xml) 内的 <appwidget-provider> 元素中定义 AppWidgetProviderInfo:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/glance_default_loading_layout"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
微件尺寸设置属性
默认的主屏幕根据定义了高度和宽度的单元格的网格在其窗口中放置微件。大多数主屏幕仅允许微件采用网格单元格的整数倍大小,例如水平方向上两个单元格,垂直方向上三个单元格。
借助微件尺寸设置属性,您可以为微件指定默认大小,并提供微件大小的下限和上限。在此上下文中,微件的默认大小是指微件首次添加到主屏幕时采用的大小。
下表介绍了与微件尺寸设置相关的 <appwidget-provider> 属性:
| 属性和说明 | |
|---|---|
targetCellWidth 和
targetCellHeight (Android 12)、
minWidth 和 minHeight |
targetCellWidth和
targetCellHeight,以及minWidth和
minHeight),以便在用户的设备
不支持targetCellWidth和
targetCellHeight时,您的应用可以回退到使用
minWidth和minHeight。如果支持,
targetCellWidth 和 targetCellHeight 属性
优先于 minWidth 和 minHeight
属性。
|
minResizeWidth 和
minResizeHeight |
指定微件的绝对最小大小。这些值指定了
微件不可读或无法使用的最小大小。使用
这些属性可让用户将微件调整为小于默认微件大小的大小。如果 minResizeWidth 属性大于 minWidth 或未启用水平大小调整,则该属性会被忽略。请参阅
resizeMode。同样,如果
minResizeHeight 属性大于
minHeight 或未启用垂直大小调整,则该属性会被忽略。 |
maxResizeWidth 和
maxResizeHeight |
指定微件的建议最大大小。如果这些值不是网格单元格尺寸的倍数,则会向上舍入到最接近的单元格大小。如果 maxResizeWidth 属性小于 minWidth 或未启用水平大小调整,则该属性会被忽略。请参阅 resizeMode。同样,
如果 maxResizeHeight 属性小于
minHeight 或未启用垂直大小调整,则该属性会被忽略。
此属性是在 Android 12 中引入的。 |
resizeMode |
指定微件可调整大小的规则。您可以使用此
属性来让主屏幕微件在横轴上可调整大小、在纵轴上可调整大小,
或者在这两个轴上均可调整大小。用户可轻触并按住微件以显示其大小调整手柄,
然后拖动水平或垂直手柄以更改布局网格上的大小。resizeMode 属性的值包括
horizontal、vertical 和 none。如需将微件声明为在水平和垂直方向上均可调整大小,请使用
horizontal|vertical。 |
示例
为了说明上表中的属性如何影响微件尺寸设置,假设有以下规范:
- 网格单元格的宽度为 30 dp,高度为 50 dp。
- 提供了以下属性规范:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
从 Android 12 开始:
使用 targetCellWidth 和 targetCellHeight 属性作为微件的默认大小。
微件的默认大小为 2x2。微件可以调整为 2x1 或 4x3。
Android 11 及更低版本:
使用 minWidth 和 minHeight 属性计算微件的默认大小。
默认宽度 = Math.ceil(80 / 30) = 3
默认高度 = Math.ceil(80 / 50) = 2
微件的默认大小为 3x2。微件可以调整为 2x1 或全屏。
其他微件属性
下表介绍了与微件尺寸设置以外的特性相关的 <appwidget-provider> 属性。
| 属性和说明 | |
|---|---|
updatePeriodMillis |
定义微件框架通过调用 onUpdate()
回调方法从
GlanceAppWidgetReceiver 请求更新的频率。我们建议尽可能降低更新频率(不超过每小时一次),以节省电池电量。
如需了解详情,请参阅 Glance 状态管理中的何时更新微件部分。 |
initialLayout |
指向用于定义 Glance 界面组合呈现之前微件的加载布局的布局资源。您可以使用库中提供的预定义加载布局:@layout/glance_default_loading_layout。 |
configure |
定义用户添加微件时启动的配置 activity。请参阅实现配置 activity 指南。 |
description |
指定要由微件选择器为您的微件显示的说明。此属性是在 Android 12 中引入的。 |
previewLayout (Android 12)
和 previewImage (Android 11 及更低版本) |
|
autoAdvanceViewId |
指定由微件的宿主自动推进的微件子视图的视图 ID。 |
widgetCategory |
声明您的微件是否可以显示在主屏幕
(home_screen)、锁定屏幕 (keyguard) 或两者上。对于 Android 5.0 及更高版本,只有 home_screen 有效。 |
widgetFeatures |
声明微件支持的功能。例如,如果您的微件的配置是可选的,请同时指定 configuration_optional 和 reconfigurable。 |
定义 GlanceAppWidget
创建一个从
GlanceAppWidget扩展的新类,并替换provideGlance方法。您可以在此方法中加载呈现微件所需的数据:class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // In this method, load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here Text("Hello World") } } }
在
GlanceAppWidgetReceiver的glanceAppWidget中实例化它:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
现在,您已使用 Glance 配置了 AppWidget。
使用 GlanceAppWidgetReceiver 类处理微件广播
GlanceAppWidgetReceiver 通过扩展底层 AppWidgetProvider 来协调微件广播和平台状态
更新。当您的微件更新、删除、启用或停用时,它会接收平台事件,并将其转换为 Compose 生命周期请求。
在清单中声明微件
在 AndroidManifest.xml 文件中将 GlanceAppWidgetReceiver 类的子类声明为广播接收器:
<receiver android:name="MyReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>
<receiver> 元素需要 android:name 属性,该属性用于指定
接收器类。接收器必须接受 ACTION_APPWIDGET_UPDATE
广播操作,在 <intent-filter> 内。
<meta-data> 元素必须将其名称标识为
android.appwidget.provider,并且 android:resource 属性必须指向
您的 AppWidgetProviderInfo XML 元数据资源 (@xml/my_app_widget_info)。
实现 GlanceAppWidgetReceiver 类
在 Glance 中,您需要扩展 GlanceAppWidgetReceiver,而不是直接扩展 AppWidgetProvider。通过将接收器链接到 GlanceAppWidget 实例来实现它。GlanceAppWidgetReceiver 中提供的主要回调按如下方式运行:
onUpdate():由 Glance 自动替换以执行组合更新。如果您手动替换onUpdate,则必须调用super.onUpdate,以便 Glance 成功启动组合 线程。onAppWidgetOptionsChanged():在首次放置或调整微件大小时调用。Glance 会在后台读取选项软件包项,以便您的布局根据运行时尺寸无缝调整。onDeleted(Context, IntArray):每当用户删除特定微件实例时调用。onEnabled(Context):在成功创建微件的第一个实例时触发。非常适合运行全局迁移。onDisabled(Context):在移除提供程序的最后一个活跃实例时调用。onReceive(Context, Intent):在特定回调方法之前拦截每个平台广播。您必须确保您编写的任何自定义接收器逻辑 都会调用super.onReceive(context, intent),并且绝不能自行调用goAsync,因为 Glance 会自动异步路由工作 。
接收微件广播 intent
在后台,GlanceAppWidgetReceiver 会过滤和处理以下基础平台微件广播 intent:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
创建界面
以下代码段演示了如何创建界面:
/* Import Glance Composables In the event there is a name clash with the Compose classes of the same name, you may rename the imports per https://kotlinlang.org/docs/packages.html#imports using the `as` keyword. import androidx.glance.Button import androidx.glance.layout.Column import androidx.glance.layout.Row import androidx.glance.text.Text */ class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // Load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here MyContent() } } @Composable private fun MyContent() { Column( modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button( text = "Home", onClick = actionStartActivity<MyActivity>() ) Button( text = "Work", onClick = actionStartActivity<MyActivity>() ) } } } }
上述代码示例执行以下操作:
- 在顶级
Column中,各项垂直放置,彼此相邻 。 Column会扩展其大小以匹配可用空间(通过GlanceModifier),并将其内容与顶部对齐 (verticalAlignment),并在水平方向上居中 (horizontalAlignment)。Column的内容使用 lambda 定义。顺序很重要。
您可以更改对齐值或应用不同的修饰符值(例如内边距)来更改组件的放置位置和大小。如需查看每个类的组件、参数和可用 修饰符的完整列表,请参阅参考 文档。
实现圆角
Android 12 引入了系统参数,用于动态自定义应用微件的圆角半径:
system_app_widget_background_radius:指定微件背景容器的圆角半径(不超过 28 dp)。- 内半径: 为防止内容剪裁,请根据系统背景轮廓为内部内容计算比例半径:
systemRadiusValue - widgetPadding
在 Glance 中,您可以使用 GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) 在组合中动态应用圆角半径尺寸设置属性。
如需在搭载 Android 11(API 级别 30)或更低版本的设备上实现向后兼容性,请实现自定义属性和自定义主题资源回退:
/values/attrs.xml<resources> <attr name="backgroundRadius" format="dimension" /> </resources>/values/styles.xml<resources> <style name="MyWidgetTheme"> <item name="backgroundRadius">@dimen/my_background_radius_dimen</item> </style> </resources>/values-31/styles.xml<resources> <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight"> <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item> </style> </resources>/drawable/my_widget_background.xml<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="?attr/backgroundRadius" /> </shape>