【安卓笔记】Widget

什么是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,那么我们就在这个方法中为按钮添加监听:
@Override
public 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的基本用法,更多用法参见文档。











郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。