Android-RemoteView-桌面小部件
Android-RemoteView-桌面小部件
学习自
《Android开发艺术探索》
https://developer.android.google.cn/guide/topics/appwidgets/#AppWidgetProvider
https://www.jianshu.com/p/88ee2bde693c
桌面小部件漫谈
桌面小部件同样是一种RemoteView,虽然桌面小部件我们很熟悉,但是为了更清晰地了解桌面小部件,我们先来看一下相关的官方文档。
下面内容来自于官方文档的桌面小部件开发指南-概览
Widgets are an essential aspect of home screen customization. You can imagine them as "at-a-glance" views of an app's most important data and functionality that is accessible right from the user's home screen. Users can move widgets across their home screen panels, and, if supported, resize them to tailor the amount of information within a widget to their preference.
小部件是桌面定制的一个重要的方面。你可以把他们想象为一个最重要的数据和从桌面可以访问的功能的一目了然的View。用户能够在桌面上移动小部件。如果提供了调整信息总量的功能,用户也可能根据自己的喜好来调整小部件的大小。下面内容来自于官方文档的桌面小部件开发指南-创建小部件
App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates. These views are referred to as Widgets in the user interface, and you can publish one with an App Widget provider. An application component that is able to hold other App Widgets is called an App Widget host.
应用小部件是一些微型的应用View,这些View能够给被嵌入到其他应用中(比如 主屏幕)并且定期接收更新。这些View在用户界面中被称作小部件,你可以通过AppWidegetProvider来发布一个小部件。一个能够容纳其他应用小部件的应用程序组件被称作应用组件持有者。
一些常见的小部件


实现桌面小部件
下面呢,我们将会实现一个桌面小部件,功能是点击小部件的时候随机切换一张狗狗的图片,效果图如下

定义一个小部件的流程如下:
- 定义小部件的布局
- 配置小部件
- 实现小部件
- 在清单文件中声明小部件
AppWidgetProvider
AppWidgetProvider是用于实现桌面小部件的类,实际上是一个广播接受者,因为他是 BroadcastReceiver 的子类,在是用该类的时候将其视为广播接受者即可。
public class AppWidgetProvider extends BroadcastReceiver
小部件的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/dogIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="@drawable/dog1" />
</LinearLayout>
配置桌面小部件
在res/xml目录下建立一个描述桌面小部件的配置信息的xml文件,命名随意,我这里命名为了 dog_appwidget_provider_info.xml ,此文件的的作用是初始化Widget。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/dog_appwidget"
android:minHeight="84dp"
android:minWidth="84dp"
android:updatePeriodMillis="10000">
</appwidget-provider>
appwidget-provider 的全部属性如下
- minHeight&minWidth定了以Widget的最小宽高,当最小宽高不是桌面cell的倍数的时候,会取最接近的值。Google为我们提供了一个公式来赋值我们计算最小宽高所对应的cell数量:
70 * n -30,n 是单元格的数量。 - updatePeriodMillis,自动更新 Widget的周期,为了处于省电的目的,系统默认的最小更新时间是
30m,但是有可能并不精确(只会再多不会再少),此属性并不能实时更新Widget。 - previewImage, 用户添加小部件时候的预览照片,如果不设置则为APP的启动图标。
- initialLayout,Widget的初始的布局文件。
- configure,定义当添加Widget小部件的时候弹出的配置Widget的Activity,如果设置了此属性,那么用来设置Widget的Activity还需要添加一个filter才行,下面会讲。
- resizeMode,如果用户定义了此属性,那么表明Widget是可以调整大小的,分为
horizontal和vertical分别表示可以横向或者纵向调整大小,当然也可以都设置horizontal|vertical表示横向纵向都可以调整大小。 - keyboard,表示Widget可以出现的位置分别
home_screen和keyguard/主界面和锁屏。需要Android5.0及以上。
Configure
上面对各个属性的解释中说明了了想要配置Widget,还需要做一些额外的工作.
首先需要配置一下Activity
<!--.......-->
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
<!--.......-->
为Activity传入参数
//获取WidgetId
this.mWidgetId = intent.extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID)
Activity还需要将WidgetId返回
var intent = Intent()
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
this.setResult(android.app.Activity.RESULT_OK, intent)
finish()
实现桌面小部件
实现Widget需要继承AppWidgetProvider类来实现我们的自己的功能。AppWidgetProvider还提供了一方法这些方法标志着Widget状态的改变,这些方法在 onReceive 方法中调用。他们如下:
- onEnable 当Widget第一此被添加到桌面的时候调用,该方法仅仅会调用一次,比如添加了两个相同的Widget,只有在添加第一个的时候才会调用此方法。
- onUpdate,当小部件被添加时,或者每次小部件更新的时候都会调用一次次方法,小部件的更新由updatePeriodMillis来指定。在此方法中我们经常会做一些初始化的操作。
- onDeleted, 没删除一次Widget都会调用一次
- onDisabled: 当最后一个该类型的Widget被删除的时候调用此方法。
- onAppWidgetOptionsChanged,当Widget大小改变时调用
- onReceive,此方法属于广播接受者的方法,在AppWidgetProvider中的主要作用是接收不同类型的广播,然后根据广播来调用上面提到的方法。我们往往会重写此方法来实现我们自己的业务逻辑。
class DogAPPWidgetProvider : AppWidgetProvider() {
companion object {
val CLICK_ACTION = "com.example.it.studyremoteview.CLICK"
}
/**
* 对接收的广播进行处理
* 当接收到广播后随机切换一个狗狗的图片
* */
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
//处理点击Widget的业务逻辑
if (intent?.action == CLICK_ACTION) {
//将会被设置的狗狗图片的资源ID
var clickIntent = Intent().setAction(CLICK_ACTION)
var pendingIntent = PendingIntent.getBroadcast(context!!, 0, clickIntent, 0)
var remoteViews = RemoteViews(context.packageName, R.layout.dog_appwidget).apply {
setImageViewResource(R.id.dogIV, getDogResId())
setOnClickPendingIntent(R.id.dogIV, pendingIntent)
}
var manager = AppWidgetManager.getInstance(context)
manager.updateAppWidget(ComponentName(context, DogAPPWidgetProvider::class.java), remoteViews)
}
}
/**
* 小部件自动更新时触发
* 在这里我们切换一下狗狗的图片
* 此方法即起到了初始化的作用,也起到了更新Widget的作用
* */
override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
appWidgetIds!!.forEach {
var clickIntent = Intent().setAction(CLICK_ACTION)
var pendingIntent = PendingIntent.getBroadcast(context!!, 0, clickIntent, 0)
var remoteViews = RemoteViews(context.packageName, R.layout.dog_appwidget).apply {
setImageViewResource(R.id.dogIV, getDogResId())
setOnClickPendingIntent(R.id.dogIV, pendingIntent)
}
appWidgetManager!!.updateAppWidget(it, remoteViews)
}
}
/**
* 随机获取一张狗狗的图片的资源ID
* */
private fun getDogResId(): Int {
//狗狗图片的资源ID
var ids = arrayOf(R.drawable.dog1, R.drawable.dog2)
var index = Random().nextInt(2)
//将会被设置的狗狗图片的资源ID
return ids.get(index)
}
}
在清单文件中声明小部件
<!--配置小部件-->
<receiver android:name=".DogAPPWidgetProvider">
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/dog_appwidget_provider_info" />
<intent-filter>
<!--小部件的单击行为-->
<action android:name="com.example.it.studyremoteview.CLICK" />
<!--这个ACTION是必须的-->
<!--这个常量如果背不过,可以在 AppWidgetManager.ACTION_APPWIDGET_UPDATE 找到-->
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>
上面的Action中,第一个 Click Action 是我们自己定义的用来表示单击事件的Action,第二个Action代表着更新Widget的Action,最后会调用 onUpdate 方法,这个Action必须存在,否则Widget不能够显式在小部件栏目中。
我们在上面提到的方法都有相应的Action,如果想调用对象的方法,请配置相应的Action
ACTION_APPWIDGET_UPDATE -> onUpdate
ACTION_APPWIDGET_DELETED -> onDeleted
ACTION_APPWIDGET_ENABLED -> onEnable
ACTION_APPWIDGET_DISABLED -> onDisable
ACTION_APPWIDGET_OPTIONS_CHANGED -> onOperationChanged
总结
本文关于桌面小部件的学习就到此为止,在接下来的文章中,还有以一个实例的方式来学习桌面小部件。
Android-RemoteView-桌面小部件的更多相关文章
- Android 桌面小部件
1. 添加AppWidgetProvider 实际上就是个带有界面的BroadcastReceiver public class SimpleWidgetProvider extends AppWid ...
- Android开发中实现桌面小部件
详细信息请参考原文:Android开发中实现桌面小部件 在Android开发中,有时候我们的App设计的功能比较多的时候,需要根据需要更简洁的为用户提供清晰已用的某些功能的时候,用桌面小部件就是一个很 ...
- Android 之窗口小部件详解--App Widget
Android 之窗口小部件详解--App Widget 版本号 说明 作者 日期 1.0 添加App Widge介绍和示例 Sky Wang 2013/06/27 1 App ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- Android 之窗口小部件高级篇--App Widget 之 RemoteViews - 跨到对岸去
在之前的一篇博文( Android 之窗口小部件详解--App Widge t)中,已经介绍了App Widget的基本用法和简单实例.这篇主要讲解 App Widget 的高级内容,即通过 Remo ...
- Android 之窗口小部件高级篇--App Widget 之 RemoteViews
Android 之窗口小部件高级篇--App Widget 之 RemoteViews 在之前的一篇博文(Android 之窗口小部件详解--App Widget)中,已经介绍了App Widget的 ...
- 桌面小部件AppWidgetProvider简单分析
1.一般桌面小部件涉及到的类 AppWidgetProvider :BroadcastRecevier子类,用于接收更新,删除通知 AppWidgetProvderInfo:AppWidget相关信息 ...
- 解决 三星Note3 桌面小部件不实时更新/不刷新 的问题
机型及问题描述:我的是三星note3 (国行 SM-N9008V),已ROOT,安装了LBE安全大师.在桌面小部件中,有些不会实时更新.比如有 滴答清单(办过的事项无法勾选),百度云音乐(歌曲播放更新 ...
- Android Widget(窗口小部件)
Android Widget简介 应用程序窗口小部件(Widget)是微型的应用程序视图,它可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新.你可以通过一个App Widget Provide ...
- 桌面小部件Wight父类AppWidgetProvider的三个方法
onUpdate()这个方法会在每次更新App Widget的时候调用,数据更新的逻辑都写在这个方法里边.而且要注意的是:在用户添加小部件的时候,会首先调用这个方法,应该在这个方法里进行初始化操作,比 ...
随机推荐
- springboot的日志框架slf4j (使用logback输出日志以及使用)
1.为什么使用logback? ——在开发中不建议使用System.out因为大量的使用会增加资源的消耗.因为使用System.out是在当前线程执行的,写入文件也是写入完毕之后才继续执行下面的程序. ...
- 「Django」contenttypes基本用法
当一张表和多个表ForeignKey关联,并且多个FK中只能选择其中一个或其中n个时,可以利用contenttypes,只需定义三个字段就搞定! contenttypes 是Django内置的一个应用 ...
- IE盒模型和W3C盒子模型的区别
其实这个问题到现在真的是没有意义了,因为早在IE6的兼容模式开始就已经弃用了IE盒子模型了,但是现在的各种面试题还是会时常出现这样的上世纪的题目,我觉得其实时纯粹的刁难. 好了,吐槽不多说了,直接上图 ...
- Scala进阶之路-Scala的基本语法
Scala进阶之路-Scala的基本语法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.函数式编程初体验Spark-Shell之WordCount var arr=Array( ...
- 鸟哥的Linux私房菜——第十三章:Vim编译器
视频链接: 土豆: B站:http://www.bilibili.com/video/av9891085/ 本章的细节还是挺多的,可是我懒啊~~
- thinkphp自学笔记
什么是MVC? M:编写模型类-对数据进行操作 用作数据处理 V:编写HTML文件-将页面显示出来 网页视图 C:编写类文件 用作逻辑处理 ThinkPHP的MVC的特点是什么: 它比较灵活并不依赖 ...
- JDK1.7安装和环境配置
进行Java或者Android开发,首先必须要搭建一个开发环境,先安装JDK,然后配置jdk环境变量.JDK现在的最高版本为JDK 1.8 ,如果我们要做Android开发,我们则需要JDK1.7以上 ...
- SpringJMS解析-JmsTemplate
目录 通用代码抽取execute() 发送消息的实现 接收消息 尽管消息接收可以使用消息监听器的方式替代模版方法,但是在发送的时候是无法替代的,在Spring中必须要使用JmsTemplate提供的方 ...
- Spring RedisTemplate操作-xml配置(1)
网上没能找到全的spring redistemplate操作例子,故特意化了点时间做了接口调用练习,基本包含了所有redistemplate方法. 该操作例子是个系列,该片为spring xml配置, ...
- 格式化 SQL 来提高效率
本文由 伯乐在线 - cucr 翻译,黄利民 校稿.未经许可,禁止转载!英文出处:msiman.ga.欢迎加入翻译小组. 背景 已格式化的SQL并不比未格式化SQL运行地更快.数据库可能真的不太在意你 ...