Android微件(续)

Google 文档

几年前前写过一篇Android桌面小插件——Widget

重新梳理一下

温故知新

问:开发一个最简单的微件总共分几步?

答:总共分4步。
1、创建一个AppWidgetProvider
2、创建一个微件布局xml;
3、创建一个微件配置xml;
4、配置清单文件;

1、创建一个AppWidgetProvider

import android.appwidget.AppWidgetProviderclass SimpleWidget : AppWidgetProvider() {}

2、创建一个微件布局xml

res/layout/widget_simple.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content">    <TextView        android:layout_width="100dp"        android:layout_height="100dp"        android:background="#AAAAAA"        android:gravity="center"        android:text="我是微件"        android:textColor="@android:color/black"        android:textSize="15sp" />RelativeLayout>

3、创建一个微件配置xml

res/xml/widget_sample.xml

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:initialLayout="@layout/widget_simple"    android:minWidth="100dp"    android:minHeight="100dp"    android:resizeMode="horizontal|vertical"    android:previewImage="@mipmap/ic_launcher"    android:updatePeriodMillis="86400000"    android:widgetCategory="home_screen" />

常用的配置(更多详细配置见google文档)

  • initialLayout :第2步创建的微件布局
  • minWidth:微件最小宽度
  • minHeight:微件最小高度
  • resizeMode:是否可以横向或纵向拉伸
  • previewImage:显示的预览样式
  • updatePeriodMillis:更新频率,默认86400000为一天
  • widgetCategory:声明应用微件是否可以显示在主屏幕 (home_screen) 和/或锁定屏幕 (keyguard) 上

4、配置清单文件

<receiver    android:name=".widget.SimpleWidget"    android:label="最简单的微件">    <intent-filter>        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />    intent-filter>    <meta-data        android:name="android.appwidget.provider"        android:resource="@xml/widget_sample" />receiver>
  • receiver-name:第1步创建的AppWidgetProvider
  • receiver-label:自定义的微件名称
  • resource:第2步创建的微件配置xml
  • 其他:固定写法

完成上述步骤,在微件中就可以看到我们刚刚创建的最简单的微件了,后续一些交互需要在我们第一步创建的AppWidgetProvider中实现。

微件布局

微件并不是支持所有布局和控件,目前支持的布局包括:

  • FrameLayout
  • LinearLayout
  • RelativeLayout
  • GridLayout

支持的控件包括:

  • AnalogClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView
  • ViewFlipper
  • ListView
  • GridView
  • StackView
  • AdapterViewFlipper

注意:能且仅能使用以上控件,包含任意其他控件都会导致加载微件时出现问题,包括AppCompatXXX等

生命周期

微件添加到桌面

  1. onEnabled
  2. onReceive :android.appwidget.action.APPWIDGET_ENABLED
  3. onUpdate
  4. onReceive :android.appwidget.action.APPWIDGET_UPDATE

微件从桌面移除

  1. onDeleted
  2. onReceive :android.appwidget.action.APPWIDGET_DELETED
  3. onDisabled
  4. onReceive :android.appwidget.action.APPWIDGET_DISABLED

定时更新

在配置xml中updatePeriodMillis属性配置的更新频率,单位为毫秒,按照官方文档的描述,该配置不能保证onUpdate正好准时回调,但是建议我们尽量降低频率,暂未验证其生命周期(其实是没收到回调)o(╥﹏╥)o,不负责任的推测应该是:[可怜]

  1. onUpdate
  2. onReceive :android.appwidget.action.APPWIDGET_UPDATE

重启APP

重启App对微件生命周期无影响

重启手机

  1. onEnabled
  2. onReceive :android.appwidget.action.APPWIDGET_ENABLED
  3. onUpdate
  4. onReceive :android.appwidget.action.APPWIDGET_UPDATE

单击事件

onUpdate中添加控件的点击监听。

我们给控件添加点击监听的常规做法是view.findviewbyid,然后setOnclickListener,在微件中稍有不同。微件中相当于是给控件的点击注册了一个广播,当控件被点击了以后,会发出一个广播,在onReceive中接收。

代码大概长这个样子

class SimpleWidget : AppWidgetProvider() {    companion object {        // 这里给布局上的4个按钮分别准备4个广播的action        private const val ACTION_1 = "com.kongqw.widght.btn1"        private const val ACTION_2 = "com.kongqw.widght.btn2"        private const val ACTION_3 = "com.kongqw.widght.btn3"        private const val ACTION_4 = "com.kongqw.widght.btn4"    }    override fun onReceive(context: Context?, intent: Intent?) {        super.onReceive(context, intent)        // 收到广播,根据action来判断点击的是哪个控件        when (intent?.action) {            ACTION_1 -> Toast.makeText(context, "点击了1", Toast.LENGTH_SHORT).show()            ACTION_2 -> Toast.makeText(context, "点击了2", Toast.LENGTH_SHORT).show()            ACTION_3 -> Toast.makeText(context, "点击了3", Toast.LENGTH_SHORT).show()            ACTION_4 -> Toast.makeText(context, "点击了4", Toast.LENGTH_SHORT).show()        }    }    override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {        super.onUpdate(context, appWidgetManager, appWidgetIds)        // 找到微件布局        val remoteViews = RemoteViews(context?.packageName, R.layout.widget_simple)        // 给布局的四个按钮绑定广播,相当于只要按钮点击,就会发一个我们设置的广播出来        remoteViews.setOnClickPendingIntent(R.id.btn_1, getPendingIntent(context, ACTION_1))        remoteViews.setOnClickPendingIntent(R.id.btn_2, getPendingIntent(context, ACTION_2))        remoteViews.setOnClickPendingIntent(R.id.btn_3, getPendingIntent(context, ACTION_3))        remoteViews.setOnClickPendingIntent(R.id.btn_4, getPendingIntent(context, ACTION_4))        // 更新微件        appWidgetManager?.updateAppWidget(appWidgetIds, remoteViews)    }    /**     * 获取PendingIntent     */    private fun getPendingIntent(context: Context?, action: String): PendingIntent? {        if (null == context) {            return null        }        val intent = Intent(action).apply {            setClass(context, SimpleWidget::class.java)        }        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)    }}

PendingIntent.getBroadcast()中的flag参数说明,详见google文档-PendingIntent

更多相关文章

  1. Android L新控件RecyclerView简介
  2. 键盘弹出以后Activity的布局方式
  3. Android其它新控件
  4. Android布局 android:gravity 和 android:layout_Gravity一些细
  5. RelativeLayout 相对布局
  6. android > 布局文件 > 背景圆角
  7. Android实现画虚线的控件
  8. Android:控件的对象修改控件的值
  9. android之datepicker控件用法

随机推荐

  1. Android的键盘事件处理
  2. 解决Assert目录下无法拷贝超大文件到SD卡
  3. Android(安卓)中string-array的用法
  4. Android给控件添加触摸回调
  5. android opengl es 2.0 draw circle
  6. Android(安卓)实现模拟地图定位功能
  7. android studio 提示Error:Default Activ
  8. Android之Action_SEND小例子
  9. android部分权限列表
  10. Android(安卓)错误 java.lang.IllegalSta