所谓桌面小控件,就是指能直接显示在Android系统桌面的小程序,比如模拟时钟等。桌面小控件是通过Broadcast的形式来进行控制的,每个桌面小控件都对应一个BroadcastReceiver。Android提供了一个AppWidgetProvider类,它是BroadcastReceiver的子类,开发者只要开发一个继承AppWidgetProvider的子类,并重写其不同状态的生命周期方法即可。AppWidgetProvider提供如下四个不同的生命周期方法:
onUpdate:负责更新桌面控件的方法;实现桌面控件通常会考虑重写该方法。
onDeleted:当一个或多个桌面小控件被删除时回调该方法。
onEnabled:当接收到ACTION_APPWIDGET_ENABLED 广播时回调该方法。
onDisabled:当接收到ACTION_APPWIDGET_DISABLED广播时回调该方法。
开发桌面小控件步骤:
1、创建一个RemoteViews对象,创建该对象时可以指定加载指定的界面布局文件。
2、如果需要改变上一步所加载的界面布局文件的内容,可通过RemoteViews对象进行修改。一般来说,界面中主要包含ImageView和TextView两种组件。
3、创建一个ComponentName对象。
4、调用AppWidgetManager的updateAppWidget方法更新桌面小控件。
下面以开发数字时钟为例(代码原型来源疯狂讲义):
AppWidgetProvider子类:
package com.home; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.os.Handler; import android.os.Message; import android.widget.RemoteViews; public class DigitClock extends AppWidgetProvider { private Timer timer = new Timer(); private AppWidgetManager appWidgetManager; private Context context; // 将0~9的液晶数字图片定义成数组 private int[] digits = new int[] { R.drawable.image0, R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5, R.drawable.image6, R.drawable.image7, R.drawable.image8, R.drawable.image9 }; // 将显示小时、分钟、秒钟的ImageView定义成数组 private int[] digitViews = new int[] { R.id.digit_image1, R.id.digit_image2, R.id.digit_image3, R.id.digit_image4, R.id.digit_image5, R.id.digit_image6 }; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { this.appWidgetManager = appWidgetManager; this.context = context; // 定义计时器 timer = new Timer(); // 启动周期性调度 timer.schedule(new TimerTask() { @Override public void run() { // 发送空消息,通知界面更新 handler.sendEmptyMessage(0x123); } }, 0, 1000); } private Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 0x123) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.digit); // 定义SimpleDateFormat对象 SimpleDateFormat df = new SimpleDateFormat("HHmmss"); // 将当前时间格式化成HHmmss的形式 String timeStr = df.format(new Date()); for (int i = 0; i < timeStr.length(); i++) { // 将第i个数字字符转换成对应的数字 int num = timeStr.charAt(i) - 48; // 将第i个图片设为对应的液晶数字图片 views.setImageViewResource(digitViews[i], digits[num]); } // 将AppWidgetProvider子类实例包装成ComponentName对象 ComponentName componentName = new ComponentName(context, DigitClock.class); // 调用AppWidgetManager将remoteViews添加到ComponentName中 appWidgetManager.updateAppWidget(componentName, views); super.handleMessage(msg); } } }; }
布局文件(digit.xml):
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/digit_image1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/digit_image2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/digit_image7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:src="@drawable/image" /> <ImageView android:id="@+id/digit_image3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/digit_image4" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/digit_image8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:src="@drawable/image" /> <ImageView android:id="@+id/digit_image5" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/digit_image6" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
配置receiver:
<receiver android:name="com.home.DigitClock" android:label="@string/app_name" > <!-- 将该BroadcastReceiver当成桌面下控件 --> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <!-- 指定桌面小控件的meta-data --> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_provider" /> </receiver>
appwidget_provide.xml:
<?xml version="1.0" encoding="utf-8"?> <!-- 指定该桌面组件的基本配置信息: minWidth:桌面小控件的最小宽度 minHeight:桌面小控件的最小高度 updatePeriodMillis:更新频率 initialLayout:初始时显示的布局 --> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/digit" android:minHeight="70dp" android:minWidth="150dp" android:updatePeriodMillis="1000" />