因公司项目需要,今天简单研究了一下桌面挂件widget的实现,写一篇总结一下思路,如有理解错的地方,望指出!
一般而言,简单的桌面挂件,如仅使用到Button, ImageView, TextView 之类的布局,只需遵循三步走:
第1步:在layout布局下编写 widget_layout.xml,定义挂件布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical"
android:gravity="center_horizontal"
android:background="@drawable/dialog_loading_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/recorder"/>
LinearLayout>
布局太简单就不废话了。
第二步:在res/xml/目录下创建一个 weiget_info.xml ,定义该挂件的属性
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="300dp"
android:minHeight="200dp"
android:initialLayout="@layout/widget_layout"
android:updatePeriodMillis="0"
android:previewImage="@drawable/recorder">
appwidget-provider>
android:updatePeriodMillis=”0” 据说这个属性在sdk1.0之后就取消了,因此挂件的更新要自己去实现了; android:previewImage=”@drawable/recorder” 设置挂件在系统中用户选择widget的预览框中看到的预览效果图; android:initialLayout=”@layout/widget_layout”绑定该widget挂件的布局文件即步骤一的文件;
第三步:自定义APPWidgetProvider子类
public class WidgetProvider extends AppWidgetProvider {
//创建更新widget时触发
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
int widgetId = appWidgetIds[0];
//声明一个pendingIntent对象指定跳转的目标界面
Intent intent = new Intent(context, SecondActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
//为RemoveView加载布局并为该布局内部控件设置点击跳转的监听
RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
view.setOnClickPendingIntent(R.id.layout, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, view);//用appwidgetmanager回调update方法
}
//删除widget时触发
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
//接受特定广播时触发
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
关于AppWidgetProvider需要清楚的是:AppWidgetProvider实质上是一个广播类,拥有广播的所有属性,可以理解为他其实是一个有界面的广播,其界面就是这个widget挂件。widget通过appwidgetprovider广播来实现布局,刷新,跳转等操作。
在这个子类里,onUpdate方法一般都要复写, onDelete方法及onReceive,onEnable,onDisable方法则可根据需求选择性的复写。
在onUpdate方法里,把weiget_layout.xml 布局文件分配给RemoteView,出此之外,还可以定义remoteView的点击触发事件PendingIntent,用PendingIntent.getActivity(mContext.getPagerName(),0,new Intent(mContext,指定的界面.class),0)的对象pendingIntent,remoteView.setOnClickPendingInent(R.id.某控件,pendingIntent);实现指定界面的跳转。方法的最后用appwidgetmanager调用updateWidget(widgetId,remoteView)方法刷新。
最后还有一个点睛之笔:Mainfest.xml文件中注册自定义的appwidgetprovider子类(广播类)
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver
android:name=".ListWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETE"/>
intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info"/>
receiver>
<application/>
receive 内部声明该广播的名称,android:name=”.自定义的widgetprovider”, 在intent-filter里面声明该widget要接收的两个系统的广播,分别是update和delete,在meta-data内部指明该类属于android.appwidget.provider(安卓系统挂件广播类),并绑定其挂件的属性文件widget_info.xml,即是步骤二的文件。
好啦,大功告成啦哈哈~