一. Widget介绍:
Widget是窗口小部件的意思,比如时间Widget,日历Widget等,可以显示一些信息,或者点击进入一个程序。比如下图的时间Widget:
下面带大家做一个很简单的Widget,点击一个按钮让按钮的文字发生变化,了解下流程。
二.Widget案例演示:
1.我们先建一个widget_layout.xml文件作为widget的布局,就是桌面上显示的布局。在这里只显示一个按钮。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="点击" >
</Button>
</RelativeLayout>
2.我们在res目录下新建一个xml目录,在里面新建一个 widget_config.xml文件,这个文件顾名思义是widget的配置文件,详细的看代码注释。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minHeight="40dp"
android:minWidth="180dp"
android:previewImage="@drawable/ic_launcher"
android:updatePeriodMillis="1000"
android:initialLayout="@layout/widget_layout"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard" >
<!--
计算宽高尺寸的公式: (70*n)-30 n为部件所需的大小(占几格) 当前的就是 3X1
minWidth widget的最小宽度
minHeight widget的最小高度
previewImage 选择部件时 展示的图标
updatePeriodMillis 更新时间间隔
initialLayout 布局文件
resizeMode 表示支持的模式,这里支持水平和垂直
widgetCategory="keyguard|home_screen" 表示widget可添加的位置 锁屏界面|桌面
-->
</appwidget-provider>
3.开始编写代码。我们新建一个 ClickAppWidget继承自 AppWidgetProvider,如果你看 AppWidgetProvider的源码会发现它继承自BroadcastReceiver。
public class AppWidgetProvider extends BroadcastReceiver {
/**
* Constructor to initialize AppWidgetProvider.
*/
public AppWidgetProvider() {
}
。。。。。。
我们重写它的onDeleted,onDisabled,onEnabled,onUpdate和onReceive方法。在什么时候调用这些方法代码里都标明了,这里只重点说下onReceive和onUpdate方法。
onReceive方法接受广播事件,可以在这里更新RemoteViews,从而更新widget。先获取RemoteViews实例, new RemoteViews()接受两个参数,一个是应用包名,一个是widget的布局文件。然后通过setTextViewText(R.id.btnSend, "点击成功")设置按钮的值,第一个参数是控件的id,第二个参数是设置内容。如果你的布局有ImageView,你可以调用setImageViewResource(viewId, srcId)设置图片。之后通过获取widget的管理者AppWidgetManager,可以看到这里是单例模式,再通过AppWidgetManager实例获取该应用的所有appWidgetIds,以数组形式返回,最终调用updateAppWidget方法,传入appWidgetIds和remoteViews两个参数就可以了。
onUpdate方法是在到达xml配置文件里 指定的更新时间或者当用户向桌面添加Widget时就被调用,所以它比onReceive方法先执行,这里我们构建了一个Intent对象,设置一个action为click,然后构建一个创建广播的PendingIntent对象,获得RemoteViews实例,调用setOnClickPendingIntent方法即可,当点击这个按钮时就会发送广播。
具体的代码就贴在下面:
public class ClickAppWidget extends AppWidgetProvider {
private static final String TAG = "ClickAppWidget";
// 删除widget的时候调用
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
Log.i(TAG, "onDeleted");
super.onDeleted(context, appWidgetIds);
}
// 当最后一个widget被删除时调用
@Override
public void onDisabled(Context context) {
Log.i(TAG, "onDisabled");
super.onDisabled(context);
}
// widget第一次被添加到桌面的时候调用
@Override
public void onEnabled(Context context) {
Log.i(TAG, "onEnabled");
super.onEnabled(context);
}
// 接受广播事件,接受一次就调用一次,和普通广播用法一样
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("click")) {
Log.i(TAG, "onReceive");
// 获得该widget的远程视图实例
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
remoteViews.setTextViewText(R.id.btnSend, "点击成功");
AppWidgetManager mWidgetManager = AppWidgetManager.getInstance(context);
//获得该应用的所有appWidgetIds
int[] appWidgetIds = mWidgetManager.getAppWidgetIds(new ComponentName(context,ClickAppWidget.class));
mWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
super.onReceive(context, intent);
}
/**
* 到达xml配置文件里 指定的更新时间或者当用户向桌面添加Widget时就被调用
* @param AppWidgetManager AppWidget的管理器
* @param appWidgetIds 桌面上 所有的widget都会被分配一个唯一的ID,存在数组里
* */
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// 创建一个Intent,设定action为click
Intent intent = new Intent("click");
// 设置pendingIntent的作用
PendingIntent mpendingIntent = PendingIntent.getBroadcast(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 获得该widget的远程视图实例
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
// 设定点击事件
remoteViews.setOnClickPendingIntent(R.id.btnSend, mpendingIntent);
// 调用updateAppWidget方法更新Appwidget
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
}
4.最后要在Manifest里添加如下代码
<receiver android:name="ClickAppWidget" >
<intent-filter>
<action android:name="click" >
</action>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" >
</action>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_config" />
</receiver>
action里的值android.appwidget.action.APPWIDGET_UPDATE是默认的,meta-data里的name也是默认值,resource的引用的是之前新建的widget配置文件。
三.结果展示
我们运行应用后,点添加小工具就可以把widget放到桌面上。
点击之前和点击之后,widget发生了变化
附上Demo下载地址:点击打开链接