什么是Widget?
App Widget是android提供的桌面小工具,它能够嵌入到桌面,并且可以定期更新自己的数据。
如下图所示:
如何创建Widget?
创建一个Widget需要以下几个组件:
1AppWidgetProviderInfo:这个类提供了Widget的元数据,比如Widget的布局,更新频率,大小等等。它通常都使用xml定义,位置为res/xml。
2.AppWidgetProvider:这个类是一个广播接收者,用来接收一些广播信息,比如widget是否可用、widget更新、widget被删除等。通常,我们需要继承这个类并复写onXXX等生命周期方法。
3.Widget布局:创建Widget需要指定其布局,这个在res/layout下定义即可。
4.AppWidgetManager:这个类可以更新Widget的状态,并可以获取已经注册的AppWidgetProvider的信息。
创建Widget的步骤:
1.定义一个类继承AppWidgetProvider:
package com.example.widget;import android.appwidget.AppWidgetManager;import android.appwidget.AppWidgetProvider;import android.content.Context;public class MyWidgetProvider extends AppWidgetProvider{ @Override public void onEnabled(Context context) { super.onEnabled(context); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDisabled(Context context) { super.onDisabled(context); }}
2.在res/layout下定义widget的布局:
比如叫widget_layout.xml
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="2dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="打开软件" android:textColor="@android:color/black" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是一个widget" /> </LinearLayout></FrameLayout>
3.在res/xml目录下创建一个xml资源,定义widget的基本信息:
比如叫:app_widget_info.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget_layout" android:minHeight="50dp" android:minWidth="290dp" android:updatePeriodMillis="86400000" ></appwidget-provider>
还有一些其他标签,用法参见文档。
4.在清单文件中配置AppWidgetProvider:
<receiver android:name="com.example.widget.MyWidgetProvider" > <intent-filter><!--action name是固定的--> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/app_widget_info" /></receiver>至此,Widget创建完成,效果如下:
这时候的button是没有点击效果的,那么如何为其增加按钮点击的响应事件呢?
那就要使用到AppWidgetManager了。
在这之前我们先介绍下Widget的生命周期,可以在上面MyWidgetProvider中打log,通过分析log我们可以得出如下结论:
1.第一个widget被拖到桌面上:onEnabled()--->onUpdate()
2.以后每个widget被拖到桌面上:onUpdate()
3.删除一个Widget:onDeleted()
4.最后一个widget被删除:onDeleted()-->onEnabled()
另外,如果你复写了onReceive方法,那么onReceive方法是最先执行的(确保要调用super.onReceive)。其实我们分析下AppWidgetProvider源码就很容易看出来,AppWidgetProvider在onReceive方法中通过判断action类型,来执行不同的业务方法,而具体的业务方法是由子类来复写的。
5.添加响应事件
既然每个widget被拖到桌面都会调用onUpdate,那么我们就在这个方法中为按钮添加监听:
@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { Log.d(TAG,"onUpdate..."); RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.widget_layout); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context,MainActivity.class),0); views.setOnClickPendingIntent(R.id.btn, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds, views); }
这里需要用到AppWidgetManager的updateAppWidget方法,这个方法需要传入widget的id和RemoteViews。这个RemoteViews很关键,我们要为按钮添加响应事件,就得调用这个类的setOnClickPendingIntent方法,当然了,它也提供了很多其他方法,诸如setTextViewText、setProgressBar等,这些方法有个共同点,那就是必须传入view的id。更多用法请查看文档。
通过上面的方法,当我们点击按钮时,就可以打开主界面了!
widget通常需要配合service使用。因为,widget需要定时更新信息,所以一个后台服务必不可少。这时候我们可以再onEnabled中启动服务,然后在服务中增加一个定时器(Timer或者AlarmManager),定期更新widget,这时候可以通过
AppWidgetManager.getInstance(context);
获取AppWidgetManager实例。
以上是widget的基本用法,更多用法参见文档。