让用户配置应用小部件

应用小部件可以配置。例如,时钟小部件可以让用户配置要显示的时区。

如果您希望让用户配置小部件的设置,请创建一个小部件配置 Activity。此活动由应用小部件主机自动启动,启动时间取决于您指定的 配置选项,是在创建小部件时还是稍后。

声明配置活动

在 Android 清单文件中将配置活动声明为普通活动。应用小部件主机使用 ACTION_APPWIDGET_CONFIGURE 操作启动它,因此该活动需要接受此意图。例如

<activity android:name=".ExampleAppWidgetConfigurationActivity">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
    </intent-filter>
</activity>

AppWidgetProviderInfo.xml 文件中使用 android:configure 属性声明活动。有关 声明此文件 的更多信息,请参阅指南。以下是如何声明配置活动的示例

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    ... >
</appwidget-provider>

该活动使用完全限定的命名空间声明,因为启动器从您的包范围之外引用它。

这就是启动配置活动所需的一切。接下来,您需要实现实际的活动。

实现配置活动

实现活动时,有两点需要牢记

  • 应用小部件主机调用配置活动,配置活动必须始终返回结果。结果必须包含由启动活动的意图传递的应用小部件 ID,该 ID 存储在意图额外的 EXTRA_APPWIDGET_ID 中。
  • 系统不会在启动配置活动时发送 ACTION_APPWIDGET_UPDATE 广播,这意味着它不会在创建小部件时调用 onUpdate() 方法。配置活动负责在首次创建小部件时从 AppWidgetManager 请求更新。但是,onUpdate() 会在后续更新中被调用,只有在第一次创建时才会被跳过。

有关如何从配置返回结果并更新小部件的示例,请参阅以下部分中的代码片段。

从配置活动更新小部件

当小部件使用配置活动时,活动负责在配置完成后更新小部件。您可以通过直接从 AppWidgetManager 请求更新来实现。

以下总结了正确更新小部件和关闭配置活动的步骤

  1. 从启动活动的意图获取应用小部件 ID

    Kotlin

    val appWidgetId = intent?.extras?.getInt(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID
    ) ?: AppWidgetManager.INVALID_APPWIDGET_ID
    

    Java

    Intent intent = getIntent();
    Bundle extras = intent.getExtras();
    int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    if (extras != null) {
        appWidgetId = extras.getInt(
                AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }
    
  2. 将活动结果设置为 RESULT_CANCELED

    这样,如果用户在到达末尾之前退出活动,系统会通知应用小部件主机配置已取消,并且主机不会添加小部件

    Kotlin

    val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    setResult(Activity.RESULT_CANCELED, resultValue)
    

    Java

    int resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(Activity.RESULT_CANCELED, resultValue);
    
  3. 根据用户的偏好配置小部件。

  4. 配置完成后,通过调用 getInstance(Context) 获取 AppWidgetManager 的实例

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    

    Java

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    
  5. 通过调用 updateAppWidget(int,RemoteViews) 使用 RemoteViews 布局更新小部件

    Kotlin

    val views = RemoteViews(context.packageName, R.layout.example_appwidget)
    appWidgetManager.updateAppWidget(appWidgetId, views)
    

    Java

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
    appWidgetManager.updateAppWidget(appWidgetId, views);
    
  6. 创建返回意图,使用活动结果设置它,然后完成活动

    Kotlin

    val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    setResult(Activity.RESULT_OK, resultValue)
    finish()
    

    Java

    Intent resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_OK, resultValue);
    finish();
    

请参阅 GitHub 上的 ListWidgetConfigureActivity.kt 示例类以了解示例。

小部件配置选项

默认情况下,应用小部件主机只会在用户将小部件添加到其主屏幕后立即启动配置活动一次。但是,您可以指定选项来让用户重新配置现有的小部件,或者通过提供默认小部件配置来跳过初始小部件配置。

让用户重新配置已放置的小部件

要让用户重新配置现有的小部件,请在 appwidget-providerwidgetFeatures 属性中指定 reconfigurable 标志。有关更多信息,请参阅有关 声明 AppWidgetProviderInfo.xml 文件 的指南。例如

<appwidget-provider
    android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
    android:widgetFeatures="reconfigurable">
</appwidget-provider>

用户可以通过触摸并按住小部件,然后点击“重新配置”按钮来重新配置其小部件,该按钮在图 1 中标记为 1

Button appears in bottom-right corner
图 1. 小部件“重新配置”按钮。

使用小部件的默认配置

您可以通过让用户跳过初始配置步骤来提供更无缝的小部件体验。为此,请在 widgetFeatures 字段中同时指定 configuration_optionalreconfigurable 标志。这会绕过在用户添加小部件后启动配置活动。如前所述,用户仍然可以 重新配置小部件。例如,时钟小部件可以绕过初始配置,并默认显示设备时区。

以下是如何将您的配置活动标记为可重新配置和可选的示例

<appwidget-provider
    android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>