最近在写一个天气app用到了桌面小部件和通知栏,记录一下,加深记忆和方便查找
1.创建桌面小部件,我这边选着直接new出来,as会自顶创建小部件所需要的的文件
接下来我们看一下,as自动为我们创建了什么文件,主要是一个java文件,和一个layout文件和一个xml文件。
我们先来看一下java文件里面的内容
public class TestAppWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
CharSequence widgetText = context.getString(R.string.appwidget_text);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_app_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
}
@Override
public void onDisabled(Context context) {
}
}
首先继承的是AppWidgetProvider 类,我们点进去可以看到AppWidgetProvider 继承的是BroadcastReceiver ,所以他本质上也是一个广播
public class AppWidgetProvider extends BroadcastReceiver {
然后我们在来看一下AppWidgetProvider类有哪些方法哪些生命周期
/**
* 每次窗口小部件被更新都调用一次该方法
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
}
/**
* 当该窗口小部件第一次添加到桌面时调用该方法
*/
@Override
public void onEnabled(Context context) {
}
/**
* 当最后一个该窗口小部件删除时调用该方法
*/
@Override
public void onDisabled(Context context) {
}
/**
* 接收窗口小部件点击时发送的广播
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
/**
* 每删除一次窗口小部件就调用一次
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
/**
* 当小部件从备份恢复时调用该方法
*/
@Override
public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
super.onRestored(context, oldWidgetIds, newWidgetIds);
}
/**
* 当小部件大小改变时
*/
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
上述方法中,我们只需着重关心一下onUpdate()方法和onReceive()方法,因为onUpdate()会在widget被添加的时候调用,我们可以在此添加一些和view交互的时间,比如点击事件。
然后再然讲一下update的代码吧
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
CharSequence widgetText = context.getString(R.string.appwidget_text);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_app_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
代码挺简单的,用一个RemoteViews ,绑定我们需要展示桌面小部件的布局R.layout.test_app_widget,然后调用setTextViewText方法去为控件设置数据,当然还有其他方法,使用功能类似,这里就不一一展示。
然后使用appWidgetManager调用updateAppWidget方法传入appWidgetId和views
appWidgetManager.updateAppWidget(appWidgetId, views);
在onUpdate()调用
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
java文件执行的一个大致流程就是这样子,然后再来看一下,as为我们创建的xml文件
这里介绍一下这些属性:
1、 android:initialLayout="@layout/test_app_widget"绑定小部件的布局文件
2、android:minWidth,android:minHeight定义了小部件的最小宽度和高度,小部件可以通过拉伸来改变widget的大小
3、android:previewImage展示定义添加小部件时显示的图标
4、android:resizeMode指定了 widget 的调整尺寸的规则。可取的值有: “horizontal”,“vertical”,“none”。”horizontal”意味着widget可以水平拉伸,“vertical”意味着widget可以竖值拉伸,“none”意味着
widget 不能拉伸;默认值是”none”。
5、widgetCategory 指定了 widget 能显示的地方:能否显示在 home Screen 或 lock screen 或 两者都可以。它的取值包括:”home_screen” 和 “keyguard
注意事项:android:previewImage定义的图标,本人测试了下,如果图片放到mipmap中,图片虽是矩形,但是显示出来还是圆形,故如果图片是矩形需要放到drawable中
然后再来看一下布局文件
这边只是用一个TextView来展示数据,代码很简单,不用过多介绍,但是在布局文件中能使用的空间还是有限定范围的
1、支持布局:FrameLayout,LinearLayout,RelativeLayout,GridLayout
2、支持控件:AnalogClock,Button,Chronometer,ImageButton,ImageView,ProgressBar,TextView,ViewFlipper,ListView,GridView,StackView,AdapterViewFlipper
最后,在清单文件里面别忘了注册
自己遇到的坑,在设置点击事件跳转的时候设置不能直接设置layout文件为跳转控件否则不能跳转,如果要整个item点击跳转,只需在父控件设置一个id,然后通过一个父控件的id来跳转即可
views.setOnClickPendingIntent(R.id.widget2_rv, pi);
如果不知道怎么跳转的同学可以去看一下我上一篇通知的文章,方法是一样的,主要通过 PendingIntent这个类来设置,贴一下简单实现的代码吧
Android 通知的使用以及SDK26以后的适配
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.item_widget2);
PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
views.setTextViewText(R.id.widget2_temper, SPUtils.getString(Constants.TEMPER_NOW, null));
views.setImageViewResource(R.id.widget2_iv, R.mipmap.test_weather);
views.setOnClickPendingIntent(R.id.widget2_rv, pi);
views.setTextViewText(R.id.widget2_high_low, SPUtils.getString(Constants.ONE_DAY_MIN_TEMPER) + "°" + "~" + SPUtils.getString(Constants.ONE_DAY_MIN_TEMPER) + "°");
appWidgetManager.updateAppWidget(appWidgetId, views);