安卓桌面小部件Widget入门指南

最近在写一个天气app用到了桌面小部件和通知栏,记录一下,加深记忆和方便查找
1.创建桌面小部件,我这边选着直接new出来,as会自顶创建小部件所需要的的文件
安卓桌面小部件Widget入门指南_第1张图片
接下来我们看一下,as自动为我们创建了什么文件,主要是一个java文件,和一个layout文件和一个xml文件。
安卓桌面小部件Widget入门指南_第2张图片
我们先来看一下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方法去为控件设置数据,当然还有其他方法,使用功能类似,这里就不一一展示。
安卓桌面小部件Widget入门指南_第3张图片
然后使用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);

你可能感兴趣的:(Android)