首页 > 代码库 > 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