关于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