安卓开发中很多控件都是Widget类的,但是我们常说的Widget指的是AppWidget,即一些可以放置在桌面的小部件。
下面用两个实例来说一下这个AppWidget怎么来用。
实例一:AppWidget的基本使用
①创建一个AppWidget的布局文件appwidget_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" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="今晚打老虎" >
</Button>
</LinearLayout>
②在res文件夹下新建一个xml文件夹,然后在里面添加一个xml文件appwidgetprovider_info.xml<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/appwidget_layout" //指定布局,这个是最重要的
android:minHeight="72dp" //最小高度
android:minWidth="294dp" //最小宽度
android:updatePeriodMillis="86400000" > //刷新时间
</appwidget-provider>
③新建一个类继承AppWidgetProvider,重写几个重要的方法
package com.example.d_appwidget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
public class AppWidget extends AppWidgetProvider {
@Override
public void onEnabled(Context context) { //首次添加AppWidget
// TODO Auto-generated method stub
super.onEnabled(context);
System.out.println("---> onEnabled");
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, //更新AppWidget
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
System.out.println("---> onUpdate");
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) { //删除AppWidget
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
System.out.println("---> onDeleted");
}
@Override
public void onDisabled(Context context) { //删除所有AppWidget
// TODO Auto-generated method stub
super.onDisabled(context);
System.out.println("---> onDisabled");
}
@Override
public void onReceive(Context context, Intent intent) { //接收到广播,比较重要的方法
// TODO Auto-generated method stub
super.onReceive(context, intent);
System.out.println("---> onReceive");
}
}
④在AndoridManifest文件中注册receiver,在application节点中添加
<receiver android:name="AppWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" >
</action>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidgetprovider_info" />
</receiver>
结果:运行后可以看到窗口小部件中我们自定义的部件
执行添加删除操作,我的理解是:执行不同操作时系统发出不同的广播,然后执行相应的方法,执行完之后系统再次发出特定广播。
实例二:在桌面上来进行手电筒操作,很多手电筒都需要先打开App然后再去开灯关灯,这有点麻烦,所以学了这个AppWidget之后我就写个这个。需要说明的是,程序本身和窗口小部件属于两个进程 ,对控件的使用和在程序本身使用是不同的,这也是最该关注的一点,也就是后面写到的PendingIntent和RemoteViews两个类。前面的步骤和实例一大致相同,主要不同是在继承类中重写的方法。
①新建一个布局文件appwidget_layout.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="vertical" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电筒-开" />
</LinearLayout>
②res文件夹下新建一个xml文件夹,新建一个appwidgetprovider_info.xml文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/appwidget_layout" >
</appwidget-provider>
③新建一个类继承AppWidgetProvider,重写几个重要的方法
package com.example.e_appwidget_flashlight;
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.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.widget.RemoteViews;
public class AppWidget extends AppWidgetProvider {
private static final String ACTION_TAG = "leelit.action.flash"; //待发出的广播
private static boolean flashOn = false;
private static Camera camera;
private static Camera.Parameters parameters;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
System.out.println("---> onUpdate");
Intent intent = new Intent(ACTION_TAG);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, //一定条件下才会触发的意图,这个意图是发出
intent, 0); //广播
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), //获得AppWidget的所有控件对象
R.layout.appwidget_layout);
remoteViews.setOnClickPendingIntent(R.id.button, pendingIntent); //此处就能点击触发上面意图,绑定为button控件
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //执行update,第一个参数代表部件ID,通常都是一个
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
if (intent.getAction().equals(ACTION_TAG)) { //点击后会发出一个广播,此处就可接收
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.appwidget_layout); //因为要操作AppWidget控件,所以要再次获取 //remoteviews和执行相应的步骤
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
ComponentName provider = new ComponentName(context, AppWidget.class);
flashOn = !flashOn; //打开或关闭电筒
if (flashOn) {
turnOnLight();
remoteViews.setTextViewText(R.id.button, "电筒-关"); //改变控件状态
appWidgetManager.updateAppWidget(provider, remoteViews);
} else {
turnOffLight();
remoteViews.setTextViewText(R.id.button, "电筒-开");
appWidgetManager.updateAppWidget(provider, remoteViews);
}
}
}
private void turnOnLight() {
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
camera.release(); //此处必须释放资源,否则后面关不了手电筒,因为相机资源一直在被占据着
}
private void turnOffLight() {
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
}
}
④在AndoridManifest文件中注册receiver,在application节点中添加。添加相应权限。
<receiver android:name="com.example.e_appwidget_flashlight.AppWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="leelit.action.flash" /> <!-- 这个广播是自定义的 -->
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidgetprovider_info" /> <!-- 资源文件 -->
</receiver>
结果:桌面添加一个部件,点击操作就可以打开或关闭手电筒了。
还有其他的一些细节就见上传的Demo吧
小结:四个步骤:①部件布局,②加载布局的xml文件,③继承AppWidgetProvider类,重写方法,④配置AndoridManifest文件