Android 12上焕然一新的小组件:美观、便捷和实用(1)

简介: Android 12上焕然一新的小组件:美观、便捷和实用(1)

Google IO 2021上重磅介绍的Android 12,号称历代设计变化最大的版本。其全新的Material You设计语言、流畅的动画特效再到焕然一新的小组件,都令人印象深刻。本文将聚焦小组件环节,谈谈它在重新设计之后的各种新特性和适配方法。


小组件在Android平台上命名为AppWidget,有的时候还被翻译成小部件、小插件和微件。说的都是一个东西:显示在Launcher上,能在Logo以外提供更多信息的特别设计。它方便用户免于打开App即可直接查看信息和进行简单的交互,在PC上、早前的Symbian上都有类似的设计。

前言

简要回顾下移动平台在小组件设计上的持续探索:


早期的Android版本缺乏美观,小组件更是常年未改。似乎除了天气、时钟等常用小组件以外鲜少使用,逐渐被人遗忘

Windows Phone的动态磁贴在自由尺寸的Logo上灵活展示信息的设计非常超前,奈何生态构建困难,早已退场

Apple向来稳重(保守),直到iOS 10才引入小组件,但负一屏限制着它的发展。直到iOS 14的全面支持才大获成功,大有后来居上的态势

VIVO紧随其后重磅推出的OriginOS则将Logo和小组件完美融合,试图一统磁贴和小组件的概念,非常值得称赞

也许是受到了友商们的持续刺激,Google终于开始重新审视小组件这个元老级功能,并在Android 12里进行了重新设计、重新出发。

1832b220aa754cd18c504acc7686a560.png

下面将结合代码实战,带领大家逐步感受Android 12里小组件的各项新特性和对应的适配方法。

1. 选择和展示的统一变化

事实上即使未做任何适配,在12上直接运行的小组件与11就有明显不同,主要表现在选择器和展示的效果。

以Chrome和Youtube Music的小组件为例:

1832b220aa754cd18c504acc7686a560.png

可以看到12上的一些变化:


选择器

顶部悬浮搜索框,可以更加快速地找到目标小组件

小组件按照App自动折叠,避免无关的小组件占用屏幕空间

App标题还对包含的小组件数目进行了提示

拖拽到桌面上之后小组件默认拥有圆角设计

11上的小组件选择器不支持搜索而且无法折叠,拖拽到桌面上也是初始的直角效果。

image.png

2. 美观的圆角设计

健康信息越发重要,手撸一个展示今日步数的小组件,搭配androidplot框架展示详细的步数图表。

override fun onUpdate(...) {
    for (appWidgetId in appWidgetIds) {
        showBarChartToWidget(context, appWidgetManager, appWidgetId)
    }
}
private fun showBarChartToWidget(...) {
    // Create plot view.
    val plot = XYPlot(context, "Pedometers chart")
    ...
    // Set graph shape
    plot.setBorderStyle(Plot.BorderStyle.ROUNDED, 12f, 12f)
    plot.isDrawingCacheEnabled = true
    // Reflect chart's bitmap to widget.
    val bmp = plot.drawingCache
    val remoteViews = RemoteViews(context.packageName, R.layout.widget_pedometer)
    remoteViews.setBitmap(R.id.bar_chart, "setImageBitmap", bmp)
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}

不用特别适配,直接运行到12上,就能有圆角效果。

1832b220aa754cd18c504acc7686a560.png

但布局需要遵从如下两点建议:


四周的边角不要放置内容,防止被切掉

背景不要采用透明的、空的视图或布局,避免系统无法探测边界去进行裁切

事实上,系统预设了如下dimension以设置默认的圆角表现。


system_app_widget_background_radius: 小组件背景的圆角尺寸,默认16dp,上限28dp

system_app_widget_inner_radius: 小组件内部视图的圆角尺寸 ,默认8dp,上限20dp

system_app_widget_internal_padding:内部视图的padding值,默认16dp

看下官方的对于内外圆角尺寸的示意图。

1672150735802.png

注意:


这些dimension可以被ROM厂商或3rd Launcher修改,不一定能保证一致性的尺寸

官方没有说明小组件的内部视图如何才能应用上内部圆角尺寸,DEMO确实也没有适配上,不知道是ROM的问题还是App的问题,有待后续的进一步研究

当然12以前的系统想要支持圆角设计也很简单:自定义radius的attribute,应用在shape drawable上,手动将drawable应用到background。具体可参考官方Sample:


https://github.com/android/user-interface-samples/tree/main/AppWidget

3. 动态的色彩效果

给小组件添加暗黑主题支持即可自动适配动态色彩。

<!-- values/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.AppWidget" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        ...
    </style>
</resources>
<!-- values-night/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.AppWidget" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <item name="colorPrimary">@color/purple_200</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/black</item>
        ...
    </style>
</resources>

image.gif

4. 改进的小组件预览

12针对小组件选择时的预览界面进行了改进,方便展示更加精准的预览效果

4.1 动态预览

之前只能使用previewImage属性展示一张预览图,功能迭代的过程中忘记更新它的话,可能导致预览和实际效果发生偏差。


12新引入了previewLayout属性用以配置小组件的实际布局,使得用户能够在小组件的选择器里看到更加接近实际效果的视图,而不再是一层不变的静态图片。


这样一来在保证效果一致的同时免去了额外维护预览图的麻烦。

<appwidget-provider
    <!-- 既存的图片属性指定UI提供的设计图 -->
    android:previewImage="@drawable/app_widget_pedometer_preview_2"
    <!-- 新的预览API里指定实际的布局 -->
    android:previewLayout="@layout/widget_pedometer"
</appwidget-provider>

左边是步数小组件一开始的设计图,右边是最后的实际效果。

1832b220aa754cd18c504acc7686a560.png

如果忘记说服UI重新作图的话,在11上的预览图会和实际效果有较大偏差。而12上不用在乎设计图是否更新,借助新的API即可直接预览实际效果,所见即所得。

1832b220aa754cd18c504acc7686a560.png

一般来说previewLayout属性最好指定小组件的实际布局。但如果预览的测试数据和实际的默认值有冲突的话,可以指定专用的预览布局,只需要确保布局的一致。

4.2 添加预览说明

description属性则可以在小组件预览的下方展示额外的说明,便于用户更好地了解其功能定位。

<appwidget-provider
    android:description="@string/app_widget_pedometer_description">
</appwidget-provider>

1832b220aa754cd18c504acc7686a560.png

需要提醒的是description属性并非12新增,但12之前的选择器不支持展示这个说明。

5. 支持新的交互控件

之前的小组件不支持CheckBox等控件,从12开始全面支持CheckBoxSwitchRadioButton三种状态控件。

下面是采用这三种控件的简单效果。

b41705914ab149ed906428aa9032a946.gif

再做个简单的待办事项以更好地说明状态小组件的使用。

// 小组件件布局里指定CheckBox控件即可
<LinearLayout ...
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:theme="@style/Theme.AppWidget.AppWidgetContainer">
    <include layout="@layout/widget_todo_list_title_region" />
    <CheckBox
        android:id="@+id/checkbox_first"
        style="@style/Widget.AppWidget.Checkbox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/todo_list_sample_1"
        Tools:text="@string/todo_list_tool" />
    ...
</LinearLayout>

1832b220aa754cd18c504acc7686a560.png

如果将同样的代码运行到11上,则会显示加载失败。


日志


AppWidgetHostView: Error inflating AppWidget AppWidgetProviderInfo(UserHandle{0}/ComponentInfo{com.example.splash/com.example.splash.widget.TodoListAppWidget}): android.view.InflateException:

Binary XML file line #13 in com.example.splash:layout/widget_todo_list: Binary XML file line #13 in com.example.splash:layout/widget_todo_list: Error inflating class android.widget.CheckBox

image.png

文本内容不确定的话,可以通过代码动态地控制文本,同时还可以监听用户的选择事件。

比如我们要展示Android开发者如今要学习的三座大山,选中的时候弹出Toast。

private fun updateAppWidget(...) {
    val viewId1 = R.id.checkbox_first
    val pendingIntent = PendingIntent.getBroadcast(...)
    val rv = RemoteViews(context.packageName, R.layout.widget_todo_list)
    rv.apply {
        // 设置文本
        setTextViewText(viewId1, context.resources.getString(R.string.todo_list_android))
        ...
        // 设置CheckBox的默认选中状态
        setCompoundButtonChecked(viewId1, true)
        // 监听相应的CheckBox的选中事件
        setOnCheckedChangeResponse(
            viewId1,
            RemoteViews.RemoteResponse.fromPendingIntent(pendingIntent)
        )
    }
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}
override fun onReceive(context: Context?, intent: Intent?) {
    ...
    val checked = intent.extras?.getBoolean(RemoteViews.EXTRA_CHECKED, false) ?: false
    val viewId = intent.extras?.getInt(EXTRA_VIEW_ID) ?: -1
    Toast.makeText(
        context,
        "ViewId : $viewId's checked status is now : $checked",
        Toast.LENGTH_SHORT
    ).show()
}

b41705914ab149ed906428aa9032a946.gif

相关文章
|
1月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
2月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
2月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
95 0
|
15天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
7月前
|
Android开发 算法 架构师
android的基础ui组件,这些知识点你会吗
android的基础ui组件,这些知识点你会吗
android的基础ui组件,这些知识点你会吗
|
2月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
2月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
52 6
|
3月前
|
存储 开发框架 数据可视化
深入解析Android应用开发中的四大核心组件
本文将探讨Android开发中的四大核心组件——Activity、Service、BroadcastReceiver和ContentProvider。我们将深入了解每个组件的定义、作用、使用方法及它们之间的交互方式,以帮助开发者更好地理解和应用这些组件,提升Android应用开发的能力和效率。
267 5
|
3月前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
4月前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!