安卓开发中很多控件都是Widget类的,但是我们常说的Widget指的是AppWidget,即一些可以放置在桌面的小部件。
下面用两个实例来说一下这个AppWidget怎么来用。
实例一:AppWidget的基本使用
①创建一个AppWidget的布局文件appwidget_layout.xml
<span style="font-size:14px;"><?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></span>②在res文件夹下新建一个xml文件夹,然后在里面添加一个xml文件appwidgetprovider_info.xml
<span style="font-size:14px;"><?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></span>③新建一个类继承AppWidgetProvider,重写几个重要的方法
<span style="font-size:14px;">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"); } } </span>④在AndoridManifest文件中注册receiver,在application节点中添加
<span style="font-size:14px;"><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></span>
结果:运行后可以看到窗口小部件中我们自定义的部件
执行添加删除操作,我的理解是:执行不同操作时系统发出不同的广播,然后执行相应的方法,执行完之后系统再次发出特定广播。
实例二:在桌面上来进行手电筒操作,很多手电筒都需要先打开App然后再去开灯关灯,这有点麻烦,所以学了这个AppWidget之后我就写个这个。需要说明的是,程序本身和窗口小部件属于两个进程 ,对控件的使用和在程序本身使用是不同的,这也是最该关注的一点,也就是后面写到的PendingIntent和RemoteViews两个类。前面的步骤和实例一大致相同,主要不同是在继承类中重写的方法。
①新建一个布局文件appwidget_layout.xml
<span style="font-size:14px;"><?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></span>②res文件夹下新建一个xml文件夹,新建一个appwidgetprovider_info.xml文件
<span style="font-size:14px;"><?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></span>③新建一个类继承AppWidgetProvider,重写几个重要的方法
<span style="font-size:14px;">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(); } } </span>
④在AndoridManifest文件中注册receiver,在application节点中添加。添加相应权限。
<span style="font-size:14px;"><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></span>结果:桌面添加一个部件,点击操作就可以打开或关闭手电筒了。
还有其他的一些细节就见上传的Demo吧
小结:四个步骤:①部件布局,②加载布局的xml文件,③继承AppWidgetProvider类,重写方法,④配置AndoridManifest文件
原文地址:http://blog.csdn.net/leelit/article/details/39611711