赞
踩
对于制作的app,widget 就只是一个静态注册的广播,widget的UI使用xml进行配置。
说明,widget 用的 layout/layout_widget.xml 文件长这样:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/widget_text" android:layout_width="100dp" android:layout_height="30dp" android:text="widget test" android:textColor="#FF1100" /> <Button android:id="@+id/widget_button" android:layout_width="20dp" android:layout_height="20dp" android:text="update" /> </LinearLayout>
class WidgetOne : AppWidgetProvider() { override fun onUpdate( context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray? ) { super.onUpdate(context, appWidgetManager, appWidgetIds) if (context != null && appWidgetManager != null) { appWidgetIds?.forEach { //操作 UI 需要通过 RemoteViews 来操作 val date = Date() //创建 RemoteViews,绑定layout文件,layout文件需要和下文的xml同一个 val views = RemoteViews(context.packageName, R.layout.layout_widget) //更新Text文本,传 View 的 id 和文言。 views.setTextViewText(R.id.widget_text, date.time.toString()) appWidgetManager.updateAppWidget(it, views) } } } }
几个主要方法说明:
onUpdate() | 发送更新广播时触发这个回调,没配置configure时添加widget触发,xml里配置的更新时长到了也会收到 |
onAppWidgetOptionsChanged() | widget 大小变化的时候回调,包括第一次添加从零到有 |
onEnable(Context) | 第一个 widget 被添加到桌面时触发回调 |
onDisabled(Context) | 最后一个 widget 从桌面移除的时候回调 |
<receiver android:name=".test.WidgetOne" android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minHeight="20dp"
android:minWidth="100dp"
android:initialLayout="@layout/layout_widget"
android:previewLayout="@layout/layout_widget"
android:updatePeriodMillis="1000">
</appwidget-provider>
不好理解的属性说明:
android:previewLayout=“@layout/layout_widget”:预看的样式,也就是点击桌面的添加小组件时,所有的小组件中这个定义的小组件显示的样子,这里使用了 layout 文件显示
android:initialLayout=“@layout/layout_widget”:初始的显示样式,添加到桌面时,没有进行修改的前提下显示的样式。
android:updatePeriodMillis=“1000”:多少时间发一次更新广播,也就是我们注册的 .test.WidgetOne 广播会收到并回调 onUpdate 方法,这个值其实是没用的,它有个最小值要求,半小时(基本都是实时更新,所以没啥用感觉),不过更新 widget 的操作我们是可以随时做的,这个只是系统会自动发给你的而已。
android:configure:如果配置了这个属性,那 widget 首次显示不会发送 update 广播去触发 onUpdate 回调更新 widget,而是直接使用这个配置里的 Activity 进行配置显示。这里没用它。
android:resizeMode=“horizontal|vertical”:widget 可以在哪个方向上调大小,横还是竖,默认就是没有,none值。设成可以改大小的话,横竖上最小值是可以定义的,用 minResizeHeight 和 minResizeWidth 定义。
<receiver android:name=".test.WidgetOne" android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="widget-test" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_xml" />
</receiver>
不能直接操作,用 RemoteViews 去操作。
//在 Activity 里写的 code,所以传了 this,实际上就是传 Context 上下文
val widgetManager = AppWidgetManager.getInstance(this)
//绑定 layout 文件
val remoteViews = RemoteViews(packageName, R.layout.layout_widget)
//操作控件需要传具体控件的 id ,而不是像正常的操作 View
remoteViews.setTextViewText(R.id.widget_text, "System.currentTimeMillis().toString()")
//这个是表示更新所有的 widget
val comName = ComponentName(this, WidgetOne::class.java)
widgetManager.updateAppWidget(comName, remoteViews)
说明:操作 View,都是用 RemoteViews 操作,事件也是,只是事件相当于一个回调,这里只用了广播方式的,意思就是,设置事件传递的 intent,在触发事件后,系统会用这个 intent 发一个广播出来,我们只要接收这个广播,然后做操作就行。
code:
val intent = Intent("widget-test")
//设置传递的 class,就是说,sendBroadCast用过吧,就是发给自己的广播,设置多个事件的时候只用Action
intent.setClass(context, WidgetOne::class.java)
//传触发事件控件的值,收到之后做判定,知道是点了啥
intent.data = Uri.parse("id:" + 888)
val pendIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val date = Date()
val views = RemoteViews(context.packageName, R.layout.layout_widget)
//这里就是设置文本
views.setTextViewText(R.id.widget_text, date.time.toString())
//这里就是设置事件,事件是点击,后面是事件后做的操作
views.setOnClickPendingIntent(R.id.widget_button, getPendIntent(context,R.id.widget_button))
appWidgetManager.updateAppWidget(appWidgetId, views)
<receiver android:name=".test.WidgetOne" android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="widget-test" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_xml" />
</receiver>
override fun onReceive(context: Context?, intent: Intent?) { val action = intent?.action if ("widget-test" == action) { val data = intent.data as Uri val viewId = data.schemeSpecificPart.toInt() //之前保存在 intent.data 的值 if (viewId == 888) { //收到之后改下了UI val widgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context?.packageName, R.layout.layout_widget) remoteViews.setTextViewText(R.id.widget_text, System.currentTimeMillis().toString()) val comName = ComponentName(context!!, WidgetOne::class.java) widgetManager.updateAppWidget(comName, remoteViews) } } super.onReceive(context, intent) }
tName(context!!, WidgetOne::class.java)
widgetManager.updateAppWidget(comName, remoteViews)
}
}
super.onReceive(context, intent)
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。