RemoteView中的应用除了有通知栏的自定义之外,还有桌面小部件也是通过RemoteView以及AppWidgetProvider来完成的。
实际上AppWidgetProvider是一个广播,即继承于BroadcastReceiver。
public class AppWidgetProvider extends BroadcastReceiver
那么我们其实可以将AppWidgetProvider当成一个特殊的BroadcastReceiver就可以了。
让我们来自定义一个桌面小部件:
首先现在res/layout/ 下创建一个xml文件,命名为appwidget.xml,这个就代表着小部件的样子是什么:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon1" />
LinearLayout>
接着我们在res/xml下创建appwidget_provider_info.xml:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/appwidget"
android:minHeight="84dp"
android:minWidth="84dp"
android:updatePeriodMillis="86400000" >
appwidget-provider>
在上面第一个属性是指小工具使用的初始化布局。第二属性和第三个属性是指最小的宽高,最后一个属性是指更新周期,每隔这么多秒就会被触发。
下面是实现类,要继承于AppWidgetProvider:
public class AppProvider extends AppWidgetProvider{
public static final String TAG = "MyAppProvider";
public static final String CLICK_ACTION = "com.example.remoteview.action.CLICK";
public AppProvider(){
super();
}
//同样是要重写onReceive()
@Override
public void onReceive(final Context context,Intent intent){
super.onReceive(context, intent);
Log.e(TAG, "action = " + intent.getAction());
if(intent.getAction().equals(CLICK_ACTION)){
Toast.makeText(context, "click it", Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//建立Bitmap
Bitmap srcBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon1);
//声明AppWidgetManager
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
for(int i = 0;i < 37;i++){
//控件图片旋转360度
float degree = (i * 10)%360;
RemoteViews remoteView = new RemoteViews(context.getPackageName(),R.layout.appwidget);
remoteView.setImageViewBitmap(R.id.imageView1,rotateBitmap(context,srcBitmap,degree));
Intent intentClick = new Intent();
intentClick.setAction(CLICK_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);
remoteView.setOnClickPendingIntent(R.id.imageView1,pendingIntent);
//updateAppWidget将会调用onUpdate
appWidgetManager.updateAppWidget(new ComponentName(context, AppProvider.class),remoteView);
SystemClock.sleep(30);
}
}
}).start();
}
}
@Override
public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds){
super.onUpdate(context, appWidgetManager, appWidgetIds);
Log.e(TAG, "onUpdate");
final int counter = appWidgetIds.length;
Log.e(TAG, "COUNTER = " + counter);
for(int i = 0;i < counter; i++){
int appWidgetId = appWidgetIds[i];
onWidgetUpdate(context,appWidgetManager,appWidgetId);
}
}
//更新部件函数
private void onWidgetUpdate(Context context,AppWidgetManager appWidgetManager,int appWidgetId){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.appwidget);
Intent intentClick = new Intent();
intentClick.setAction(CLICK_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);
//桌面小部件将会被点击触发,发送PendingIntent
remoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
//变换Bitmap的矩阵
private Bitmap rotateBitmap(Context context,Bitmap srcBitmap,float degree){
Matrix matrix = new Matrix();
matrix.reset();
matrix.setRotate(degree);
Bitmap tmpBitmap = Bitmap.createBitmap(srcBitmap,0,0,srcBitmap.getWidth(),srcBitmap.getHeight(),matrix,true);
return tmpBitmap;
}
}
对了,别忘记了还有继承于BroadcastReceiver我们还是需要注册,注册有点点不一样。如下:
<receiver android:name=".AppProvider">
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_provider_info">
meta-data>
<intent-filter>
<action android:name="com.example.remoteview.action.CLICK"/>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
intent-filter>
receiver>
第一个Action用来标识点击行为,第二个Action是声明为AppWidget必须存在的action。
这样就完成了桌面小工具的实现了。