首页 > 代码库 > RemoteViews用法二:可以接收点击事件并改变外观的widget
RemoteViews用法二:可以接收点击事件并改变外观的widget
关于widget简单的用法参考:RemoteViews用法一:widget简单用法
这篇博客完成一个可以接收点击事件并改变外观的widget,并简要总结,最后附上源码下载地址。
Demo代码:
1.定义Widget布局XML /res/layout/widget_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/widget_start" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="start" /> <Button android:id="@+id/widget_stop" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="stop" /> <TextView android:id="@+id/widget_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="text" android:textColor="#fff" /> </LinearLayout>
2.定义Widget属性文件 /res/xml/widget_info.xml 这里不附代码
3. 创建FirstWidgetProvider子类,实现onUpdate()等函数。
package net.qingtian.appwidget2; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.RemoteViews; /** * AppWidgetProvider子类 * @author qingtian 2014年11月21日15:02:53 */ public class FirstWidgetProvider extends AppWidgetProvider { private static final String TAG = "qingtian"; // 定义一个常量字符串,该常量用于命名Action private static final String UPDATA_STATUS_FROM_WIDGET_START = "net.qingtian.UPDATA_STATUS_FROM_WIDGET_START"; private static final String UPDATA_STATUS_FROM_WIDGET_STOP = "net.qingtian.UPDATA_STATUS_FROM_WIDGET_STOP"; @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "onReceive"); String action = intent.getAction(); if (UPDATA_STATUS_FROM_WIDGET_START.equals(action)) { // 改变widget外观 setViewStatus(context, 1); } else if (UPDATA_STATUS_FROM_WIDGET_STOP.equals(action)) { // 改变widget外观 setViewStatus(context, 0); } else { super.onReceive(context, intent);// 这里一定要添加,eles部分,不然,onReceive不会去调用其它的方法。但是如果把这条语句放在外面,就会每次运行onUpdate,onDeleted等方法,就会运行两次,因为UPDATE_ACTION.equals(action)配置成功会运行一次,super.onReceive(context, // intent)配置成功又会运行一次,后都是系统自定义的。 } } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.i(TAG, "onupdated"); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // 设置开始监听 Intent intentStart = new Intent(); // 为Intent对象设置Action intentStart.setAction(UPDATA_STATUS_FROM_WIDGET_START); // 使用getBroadcast方法,得到一个PendingIntent对象,当该对象执行时,会发送一个广播 PendingIntent pendingIntentStart = PendingIntent.getBroadcast(context, 0, intentStart, 0); remoteViews.setOnClickPendingIntent(R.id.widget_start, pendingIntentStart); // 设置停止监听 Intent intentStop = new Intent(); // 为Intent对象设置Action intentStop.setAction(UPDATA_STATUS_FROM_WIDGET_STOP); // 使用getBroadcast方法,得到一个PendingIntent对象,当该对象执行时,会发送一个广播 PendingIntent pendingIntentStop = PendingIntent.getBroadcast(context, 0, intentStop, 0); remoteViews .setOnClickPendingIntent(R.id.widget_stop, pendingIntentStop); appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDeleted(Context context, int[] appWidgetIds) { Log.i(TAG, "onDeleted"); super.onDeleted(context, appWidgetIds); } @Override public void onDisabled(Context context) { Log.i(TAG, "onDisabled"); super.onDisabled(context); } @Override public void onEnabled(Context context) { Log.i(TAG, "onEnabled"); super.onEnabled(context); } /** * 设置widget的状态,即改变textView里面的文字 * * @param status */ public void setViewStatus(Context context, int status) { RemoteViews remoteViews = null; if (status == 0) {// 结束 remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); remoteViews.setTextViewText(R.id.widget_text, "0 结束"); } else if (status == 1) {// 开始 remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); remoteViews.setTextViewText(R.id.widget_text, "1 开始"); } else { return; } // remoteViews.setTextViewText(R.id.test_text, "data "+data); // getInstance(Context context) Get the AppWidgetManager instance to // use for the supplied Context object.静态方法。 AppWidgetManager appWidgetManager = AppWidgetManager .getInstance(context); ComponentName componentName = new ComponentName(context, FirstWidgetProvider.class); appWidgetManager.updateAppWidget(componentName, remoteViews); } }
4.在manifest中注册receiver,添加一个action为 android.appwidget.action.APPWIDGET_UPDATE 的IntentFilter,并添加如下<meta- data>标识:
<receiver android:name="net.qingtian.appwidget2.FirstWidgetProvider" android:label="wid2" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="net.qingtian.UPDATA_STATUS_FROM_WIDGET_START" /> <action android:name="net.qingtian.UPDATA_STATUS_FROM_WIDGET_STOP" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info" > </meta-data> </receiver>
总结:
1.关于事件处理的大体流程:由于widget和原来的程序是相对独立的,所以它的事件监听也有些与众不同,主要就是广播的来传递消息。大体分为两步:a.设置widget里的组件被点击后发送广播。b.我们写的AppWidgetProvider的子类可以接收这些广播,然后响应事件,比如改变widget外观,改变service的状态等。
2.关于设置widget里的组件的onclick事件监听:通过widget的生命周期来看,初始化widget里组件的事件监听放在onUpdate方法里。步骤为:构造RemoteViews->为RemoteViews里的组件设置onClick事件->把RemoteViews与widget关联。在这个demo里,我为组件添加的事件监听处理是发送广播。
3.关于接收这些广播,首先AppWidgetProvider就是继承自BroadcastReceiver,只是它默认处理了一些和widget的广播,我们需要去重写onRecevie,但是要保证不能影响他处理默认的广播的功能。
4.在给widget里的组件设置监听时,用到RemoteViews,由于RemoteViews的特殊性,所以设置的代码和平时设置监听的代码有点区别,而且能设置的事件监听类型也比较有限,具体区别参考RemoteViews。
源码下载:
http://download.csdn.net/detail/u011647962/8184179
RemoteViews用法二:可以接收点击事件并改变外观的widget