原文连接。
很长时间以来,微件(Widgets) 一直是Android核心体验的一部分,许多应用程序有效地使用微件来增加用户参与度。用户喜欢微件,因为它能够在不启动应用程序的情况下使用应用程序的功能,并自定义设备的主屏幕。
Android 12更新了现有的微件API,并修改了微件的设计,使之与“Material You”的设计语言保持一致。这些更改允许您使用设备主题颜色和圆角来构建更好看的微件,同时增强 搜索和放置微件 的可发现性和视觉效果。
更改前(Android 11)与更改后的浅色和深色主题(Android 12)相对比
在这个迷你系列文章中,我们将了解如何为Android 12更新您的微件。在这一部分中,我们将看到一些简单的更改,这些更改将使您的微件在运行Android 12的设备上看起来很棒,同时在旧版本的Android上提供一致的体验。在第二部分中,我们将了解下新的API,它将使您的微件更加个性化、响应更灵敏,并提供更多的交互性。
视觉变化
毫无疑问,风格和设计的变化对用户来说是最明显的。更新例如颜色和(圆)角半径之类的视觉元素,可立即呈现更清爽的外观。要开始实现这些更改,我们建议创建一个自定义主题。
添加动态颜色
Material You 的目标是实现更个性化的用户体验。在Android 12上,动态颜色使您的微件与其他微件和系统更加一致。微件可以使用系统的默认主题Theme.DeviceDefault.DayNight
,并在微件的UI元素上使用主题颜色属性。
要做到这一点,你需要为低于31的版本从父DeviceDefault创建一个自定义主题。
values/themes.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.AppWidget.AppWidgetContainer"
parent="@android:style/Theme.DeviceDefault" />
对于版本31,使用父主题DeviceDefault.DayNight
创建一个自定义主题。
values-v31/themes.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.AppWidget.AppWidgetContainer"
parent="@android:style/Theme.DeviceDefault.DayNight" />
或者,如果你的app使用Material Components,则可以使用
Theme.MaterialComponents.DayNight
作为基本主题,而不是Theme.DeviceDefault
。
要使微件动态地采用系统颜色,请将此主题指定给微件,并在其他views上使用主题颜色属性。
layout/widget_checkbox_list_title_region.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
...
<TextView android:id="@+id/checkbox_list_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:text="@string/grocery_list"
android:textColor="?android:attr/textColorPrimary" />
<ImageButton
android:layout_width="@dimen/widget_element_min_length"
android:layout_height="@dimen/widget_element_min_length"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:contentDescription="@string/add_button_grocery_list_content_description"
android:src="@drawable/ic_add_24"
android:tint="?android:attr/colorAccent" />
...
静态颜色 vs. 浅色/深色 主题中的动态颜色
圆角
从Android 12开始,圆角自动应用于微件。这意味着微件的内容可能会被应用的拐角遮罩切断。为了避免这种情况,并为其他微件和系统提供更一致的外观和用户体验,您可以使用
向微件的轮廓添加圆角,使用 system_app_widget_background_radius
向微件内的 views 添加圆角。这个值应该比 system_app_widget_inner_radius
system_app_widget_background_radius
小8dp。
在执行此操作时,请记住,如果您的微件的内容靠近其角落,则此内容可能会被裁剪。要解决这个问题,您需要添加足够的 padding,以避免微件的内容与圆角冲突。
values/attrs.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetPadding" format="dimension" />
<attr name="appWidgetInnerRadius" format="dimension" />
<attr name="appWidgetRadius" format="dimension" />
</declare-styleable>
values/themes.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.AppWidget.AppWidgetContainerParent"
parent="@android:style/Theme.DeviceDefault">
<!-- 微件外部边界的半径,用以生成圆角。-->
<item name="appWidgetRadius">16dp</item>
<!-- 微件内部view边界的半径,用以生成圆角。它需要是8dp或小于 appWidgetRadius 的值。-->
<item name="appWidgetInnerRadius">8dp</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainer"
parent="Theme.AppWidget.AppWidgetContainerParent">
<!-- 应用 padding 以避免微件的内容与圆角冲突。-->
<item name="appWidgetPadding">16dp</item>
</style>
values-v31/themes.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.AppWidget.AppWidgetContainerParent"
parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="appWidgetRadius">
@android:dimen/system_app_widget_background_radius</item>
<item name="appWidgetInnerRadius">
@android:dimen/system_app_widget_inner_radius</item>
</style>
values/styles.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<style name="Widget.AppWidget.AppWidget.Container"
parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:background">
?android:attr/colorBackground</item>
</style>
如果你的
minTargetSDK
低于版本 21,则需要为版本 21 提供样式,因为在 drawables 中使用的android:attr/colorBackground
要求 API 级别 为21。
现在您已经创建了一个主题,您可以在微件的布局上设置样式。
layout/widget_grocery_list.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<LinearLayout
style="@style/Widget.AppWidget.AppWidget.Container">
...
</LinearLayout>
之前 vs. 自动圆角遮罩 vs. 应用 padding 的圆角
过渡效果
Android 12 在从微件启动 app 时提供了改进的过渡效果。这个过渡转场由系统自动处理,并且在旧版本的Android上不会显示。要启用它,您需要在微件布局的根元素上指定一个id
并将其值设置为 android:id/background
。
<LinearLayout
android:id="@android:id/background">
...
</LinearLayout>
慢速下的过渡效果
如果您的微件使用 broadcast trampolines ,这意味着您的微件在用户单击时创建一个 PendingIntent
,以从broadcast receiver 或 service 启动 activity,则不会使用此动画。
新的微件选择器改进
预览
Android 12有一个新的和改进的微件选择器。新的微件选取器不使用静态 drawable 资源,而是使用 XML 布局动态创建微件的缩放预览。
如果您的微件不包含动态元素,如 ListView
或GridView
,您可以简单地使用微件的布局进行预览。
要实现这一点,需要将默认值直接设置为原始布局。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<TextView
style="@style/Widget.AppWidget.Checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/widget_title_preview" />
<TextView
style="@style/Widget.AppWidget.Checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/widget_subject_preview" />
在布局上设置默认值可能会导致在应用实际值之前,假占位符值显示的稍微延迟。要防止出现这种情况,您也可以为预览创建单独的布局文件,并应用自定义预览主题。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<resources>
<!-- 声明属性 -->
<attr name="widgetTitlePreview" format="string" />
<attr name="widgetSubjectPreview" format="string" />
<!-- 声明样式 -->
<style name="Theme.MyApp.Widget"
parent="@style/Theme.DeviceDefault.DayNight.AppWidget">
<item name="widgetTitlePreview"></item>
<item name="widgetSubjectPreview"></item>
</style>
<style name="Theme.MyApp.Widget.Preview">
<item name="widgetTitlePreview">Preview Title</item>
<item name="widgetSubjectPreview">Preview Subject</item>
</style>
</resources>
一旦有了预览主题,就可以将其应用到布局中的预览项。
layout/my_widget_preview.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<LinearLayout ...>
<include layout="@layout/widget_header"
android:theme=”@style/Theme.MyApp.Widget.Preview” /></LinearLayout>
layout/my_widget_actual.xml
<LinearLayout ...>
<include layout="@layout/widget_header"
android:theme=”@style/Theme.MyApp.Widget” />
</LinearLayout>
最后,您需要设置微件的布局,以指定为 appwidget-provider
的 previewLayout
属性。
xml/app_widget_info_checkbox_list.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<appwidget-provider
android:previewLayout="@layout/widget_grocery_list"
...
/>
静态预览 vs. 缩放预览
对于 ListView
、GridView
或 Stack
中显示的多个项目,无法直接在布局上设置默认值。在这种情况下,您可以为微件预览创建另一个布局,并在此布局中设置多个硬编码项。
执行此操作时,最好不要复制整个布局,而是使用 <include>
标签来重用使用默认值的布局部分。 您可以将这个新布局设置为 appwidget-provider
的 previewLayout
属性。
描述
您还可以设置 description
属性,以提供要在微件选择器中显示的描述。虽然这是可选的,但提供描述可以帮助用户更好地理解微件的功能。
app_widget_info_checkbox_list.xml
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
<appwidget-provider
android:description="@string/app_widget_grocery_list_description"
...
/>
微件描述
总结
这并不难,对吧? 在这篇文章中,你已经了解了如何更新微件的设计,并在微件选择器中提供更好的用户体验。 这些都是很容易完成的任务,你可以开始为 Android 12 更新你的微件,你的用户会立即注意到视觉上的差异。
但是,这还不是全部。在下一篇文章中,我们将了解下新的 API,它将使您的微件更加个性化、响应速度更快,并提供更多的交互性。