头图

For a long time, widgets have been a core part of the Android user experience. Many applications use widgets to increase user stickiness. The reason why users are happy to use widgets is that they can use application functions without opening the application and can customize the home screen of the device.

Android 12 updates the existing Widget API and reshapes the design of widgets to fit the " Material You " design language. These updates can help you use the device's theme colors and rounded corners to build more beautiful widgets, thereby improving the discoverability and visual perception of widgets when searching and placing them.

△ 对比更新之前 (Android 11) 和更新后的浅色和深色主题 (Android 12)

△ Compare the light and dark themes before (Android 11) and after the update (Android 12)

In this series, we will take you to update the widget to adapt to Android 12. In this article, we will make some simple modifications to make your widgets look more refined on Android 12 devices and provide a consistent user experience on older devices. In the second article, we will learn about new APIs that can make widgets more personalized, responsive and interactive.

Visual changes

For users, there is no doubt that the most intuitive visual changes are changes in style and design. Update visual elements, such as colors and rounded corners, to give users a refreshing appearance. To add these changes, we recommend that you create a custom theme.

adds dynamic color

Material You aims to provide a more personalized user experience. In Android 12, dynamic colors can keep your widgets in a consistent style with other widgets and the system. The widget can use the system default theme Theme.DeviceDefault.DayNight , and use the theme color attribute in the UI element of the widget.

https://www.bilibili.com/video/BV13V41177zj/?aid=418337899&cid=344803575&page=1

△ Material Design update list

For devices with SDK level lower than 31, you need to create a custom theme that inherits from DeviceDefault.

values/themes.xml
<style name="Theme.AppWidget.AppWidgetContainer"
   parent="@android:style/Theme.DeviceDefault" />

For devices with SDK level 31, use the theme DeviceDefault.DayNight to create a custom theme.

values-v31/themes.xml
<style name="Theme.AppWidget.AppWidgetContainer" 
   parent="@android:style/Theme.DeviceDefault.DayNight" />
Or, if your application uses [Material Components](), you can use Theme.MaterialComponents.DayNight as the base theme instead of Theme.DeviceDefault .

In order to enable your widget to dynamically adapt to the system color, you can configure the theme on your widget and use the theme color attribute on other views of the widget.

layout/widget_checkbox_list_title_region.xml
...
<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" />
...

△ 在浅色/深色主题中静态颜色与动态颜色的对比

△ Contrast between static color and dynamic color in light/dark theme

rounded corners

Starting from Android 12, rounded corners will be automatically applied to widgets. This also means that the rounded corners will crop part of the widget's content. In order to avoid such problems and provide a consistent appearance and user experience with other widgets and system styles, you can use system_app_widget_background_radius to add rounded corners to the background of the widget, and use system_app_widget_inner_radius add rounded corners to the widget’s view Horn. The latter value needs to be system_app_widget_background_radius smaller than 0613b09845fc7f.

When adding the above modifications, please note that if your widget contains content near the corner area, these content may be cut off. To solve this problem, you need to add padding large enough to avoid conflicts between the content of the widget and the rounded corners.

values/attrs.xml
<declare-styleable name="AppWidgetAttrs">
   <attr name="appWidgetPadding" format="dimension" />   
   <attr name="appWidgetInnerRadius" format="dimension" />
   <attr name="appWidgetRadius" format="dimension" />
</declare-styleable>
values/themes.xml
<style name="Theme.AppWidget.AppWidgetContainerParent"
   parent="@android:style/Theme.DeviceDefault">
<!-- 微件的外轮廓的圆角半径 -->
   <item name="appWidgetRadius">16dp</item>
<!-- widget 内部视图边缘的圆角半径。它的值为 8 dp 或者小于 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
<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
<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>
If your minTargetSDK less than 21, then you need to provide a suitable style SDK version 21, because drawable use on android:attr/colorBackground need the SDK version is at least 21.

So far you have created the theme, and now you can set the style on the layout of the widget.

layout/widget_grocery_list.xml
<LinearLayout
   style="@style/Widget.AppWidget.AppWidget.Container">
   ...
</LinearLayout>

△ 对比原有风格、自动圆角效果以及带有圆角和 padding 的效果

△ Contrast the original style, automatic rounded corner effect, and the effect with rounded corners and padding

transition

When the app is opened through the widget, Android 12 provides a transition effect. This transition effect is automatically processed by the system and will not appear on older versions of Android. To enable this effect, you need to specify an id on the root element of the widget layout and set its value to android:id/background.

<LinearLayout
   android:id="@android:id/background">
   ...
</LinearLayout>

△ 过渡效果的慢放动画

△ Slow animation of transition effect

If your widget uses broadcast trampoline , that is to say, your widget creates a PendingIntent when the user clicks, and launches the Activity through a broadcast or service. In this case, the transition animation will not take effect.

Optimization of

preview

Android 12 includes a new and improved widget selector. Unlike using static drawable resources, the new widget selector uses an XML layout to dynamically create zoomed widget previews.

If your widget does not contain dynamic elements, such as ListView or GridView, you can use the layout of the widget to preview it.

To achieve preview, you need to set the default value directly to the original layout.

<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" />

Setting the default value on the layout may cause a small amount of delay, because the value of the placeholder will be enabled first before the actual value. To avoid this problem, you can create a separate layout file for the preview and enable a custom preview theme.

<resources>
   <!-- 声明属性-->
   <attr name="widgetTitlePreview" format="string" />
   <attr name="widgetSubjectPreview" format="string" />
   <!-- 声明 style -->
   <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>

After creating the preview theme, you can apply it to the preview elements in the layout.

layout/my_widget_preview.xml
<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>

Finally, you need to set the layout of the appwidget-provider the previewLayout attribute of 0613b09845ff62.

xml/app_widget_info_checkbox_list.xml
<appwidget-provider
   android:previewLayout="@layout/widget_grocery_list"
   ...
/>

△ 对比静态预览效果与缩放预览效果

△ Comparison of static preview effect and zoom preview effect

ListView , GridView or Stack that displays multiple elements, it is impossible to directly set default values on the layout. For these views, you can create another layout for the widget preview and set a fixed value in the layout.

To achieve the above operation, the recommended best practice is to use the <include> tag to reuse part of the layout to enable the default value without duplicating the entire layout. You can set the new layout appwidget-provider of previewLayout property.

Description

You can also set the description attribute as the description information to be displayed on the widget selector. Although this is optional, providing description information can help users better understand the functionality of the widget.

app_widget_info_checkbox_list.xml
<appwidget-provider
  android:description="@string/app_widget_grocery_list_description"
  ...
/>

△ 微件描述

△ Widget description

summary

In this article, we showed you how to update the widget design and provide a better user experience in the widget selector. The above content can quickly update your widget to adapt to Android 12, and your users can see the very intuitive difference.

But this is not all. In the next article, we will learn about the new API, which can make your widgets more personalized, responsive and interactive.

You are welcome to click here to submit feedback to us, or share your favorite content or problems found. Your feedback is very important to us, thank you for your support!


Android开发者
404 声望2k 粉丝

Android 最新开发技术更新,包括 Kotlin、Android Studio、Jetpack 和 Android 最新系统技术特性分享。更多内容,请关注 官方 Android 开发者文档。