前言
Anroid上的桌面小组件很早以前就有了,相比iOS的小组件一出来就大火不同,Android桌面小组件一直很难用,最近看到了Google微信号推送的文章:
我以为Android小组件间要崛起了!!开心的去看了[官网demo](user-interface-samples/AppWidget at main · android/user-interface-samples (github.com))
在Android12上主要更新了可调整窗口大小,不同主题下的效果,和一些圆角边距等细节设置,看起来还是不太聪明的样子
快速上手Widget
桌面小组件被Google成为微件:AppWidget
,查看官网文档
右键菜单栏中创建Widget组件,其会自动创建相关类:
我们以创建一个TODO组件为例
相关类
- AppWidgetProvider
组件类,通过广播与其连接,可以通过
onUpdate
,onEnable
,onDelete
等方法与组件进行通信。 这里我们新建TodoWidget:
class TodoWidget : AppWidgetProvider() {
override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) {
}
override fun onEnabled(context: Context) {
}
override fun onDisabled(context: Context) {
}
}
同时我们需要在Mainfest.xml中注册:
<receiver
android:name=".TodoWidget"
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/todo_widget_info" />
</receiver>
widgetProvider继承自广播,本身可以通过onReceive()来接受消息
- AppWidgetProviderInfo
提供了组件的各种信息,尺寸、布局、预览等信息,以xml文件的形式创建
在资源文件下新建xml目录:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_widget_description"
android:initialKeyguardLayout="@layout/todo_widget_min"
android:initialLayout="@layout/todo_widget_min"
android:minWidth="110dp"
android:minHeight="110dp"
android:previewImage="@drawable/example_appwidget_preview"
android:previewLayout="@layout/todo_widget_min"
android:resizeMode="horizontal|vertical"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />
创建布局
Widget组件布局基于:RemoteViews有很多特殊性,这也是目前Android小窗口的局限,很多组件都无法使用,交互也表困难。
RemoteViews 可以支持以下布局类:
FrameLayout
LinearLayout
RelativeLayout
GridLayout
以及以下微件类:
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
对于我们常见的RecyclerView、约束布局都不支持!
布局代码可以看Demo,这里说下狂口调整时候的布局变化,调整窗口的大小在Android12上才可用
我们可以在WidgetProvider类中的onUpdate中更新组件:
override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
创建多个RemoteView,我这里创建了三个不同布局对应不同尺寸:
@SuppressLint("RemoteViewLayout")
internal fun updateAppWidget( context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int ) {
val remoteViewsMin = RemoteViews(
context.packageName,
R.layout.todo_widget_min
)
val remoteViewsNormal = RemoteViews(
context.packageName,
R.layout.todo_widget_normal
)
val remoteViewsMax = RemoteViews(
context.packageName,
R.layout.todo_widget_max
)
/*不同大小控件对应不同布局*/
val viewMapping: MutableMap<SizeF, RemoteViews> = mutableMapOf()
viewMapping[SizeF(180.0f, 110.0f)] = remoteViewsMin
viewMapping[SizeF(230.0f, 180.0f)] = remoteViewsNormal
viewMapping[SizeF(270.0f, 300.0f)] = remoteViewsMax
/*只有在Android12以上版本才支持*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))
}else{
appWidgetManager.updateAppWidget(appWidgetId, remoteViewsNormal)
}
}
查看效果
长按app图标就可在桌面添加组件,不同系统操作方式不一样。
通信交互
打开App,在Activity做出响应
widget和宿主app不属于同一进程,可以通过
PendingIntent
通信,和传统的Intent有点不一样,简言之:PendingIntent含有app的context,可以在外部进程打开app进程,PendingIntent不是立即执行的。
RemoteView设置点击事件
setOnClickPendingIntent(R.id.add, createPendingIntent(context,R.id.add))
createPendingIntent()是一个将id传给activity的方法,你也可以设置其他信息,在activity做出响应
private fun createPendingIntent(context: Context,@IdRes id:Int):PendingIntent{
/*打开APP intent*/
val activityIntent = Intent(context, MainActivity::class.java).apply {
setData(Uri.parse("harvic:$id"))
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
}
val appOpenIntent = PendingIntent.getActivity(
context,
1,
activityIntent,
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
return appOpenIntent
}
在onReceive中处理:
和上述的基本一样,根据id来处理不同的点击事件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val clickIntent = PendingIntent.getBroadcast(
context,
2,
Intent(context, TodoWidget::class.java).apply {
putExtra(EXTRA_VIEW_ID, R.id.title)
},
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
setOnClickPendingIntent(R.id.title,clickIntent)
}
最后
点击查看:项目代码,欢迎大佬们的Star
感觉Andorid桌面小组件依旧不够完善,和以前相比也没啥大大的改变。=.=
之前的文章介绍了网络封装、组件化、基础工具等,有兴趣的可以查看:
- 写一个MVVM快速开发框架(一)基础类封装
- 写一个MVVM快速开发框架(二)组件化改造
- 写一个MVVM快速开发框架(三)单Activity+多Fragment模式
- 写一个MVVM快速开发框架(四)优雅的数据处理 – 掘金 (juejin.cn)
还有一些关于UI的基础工具:
今天的文章Android 12桌面小组件分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/20327.html