第7章 App Widgets

App Widgets是一个应用程序的微型视图,可以嵌入到其他应用程序(如主屏幕)并且能够定期更新。你可以发布一个应用程序的App Widget,而这些视图称为窗口的用户界面。一个应用程序组件,可以支持其他应用程序的App Widgets称为App Widget的主机(host)。下面的截图是显示音乐的App Widget。

该文档将介绍如何在应用程序里发布和使用App Widget。

7.1 基础知识

要创建一个App Widget,您需要了解以下几点:

◆AppWidgetProviderInfo对象:
描述了一个App Widget的元数据,如在App Widget的布局,更新频率,和AppWidgetProvider类。都应在XML中定义。
◆AppWidgetProvider类的实现:
定义一个基于广播事件与App Widget的接口方法。通过它,您将收到广播对App Widget进行更新,启用,禁用和删除。
◆视图布局:
在XML中初步定义App Widget布局。
此外,还可以实现App Widget可配置的Activity。当用户添加您的App Widget,并允许他或她在创建时修改设置时启动这个可配置的Activity。
该文档将介绍如何在应用程序里发布和使用App Widget。

7.2 在Manifest.xml中声明App Widgets

首先,在您的应用程序的AndroidManifest.xml文件中应声明AppWidgetProvider类。例如代码清单7-1所示:

<receiver android:name="ExampleAppWidgetProvider" ><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-data android:name="android.appwidget.provider"android:resource="@xml/example_appwidget_info" />
</receiver>

代码清单 7-1

<receiver>节点需要的android:name属性,在App Widget中指定使用AppWidgetProvider。 <intent-filter>节点必须包含一个<action>节点的name属性。此属性指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE广播。这是唯一的广播,你必须明确声明。在AppWidgetManager自动发送其他App widget广播到AppWidgetProvider是必要的。<meta-data>节点指定的AppWidgetProviderInfo的资源,需要以下属性:

android:name - 指定的元数据的名称。使用android.appwidget.provider识别作为

◆AppWidgetProviderInfo描述符的数据。

◆android:resource - 指定的AppWidgetProviderInfo的资源位置。

7.3 添加AppWidgetProviderInfo元数据

AppWidgetProviderInfo是定义App Widget的本质,例如其最小的布局尺寸,初始布局资源,如何更新App Widget,和(可选)配置Activity,在创建时发起。在XML资源文件中定义AppWidgetProviderInfo对象,使用<appwidget-provider>节点和在项目的res / xml/文件夹中保存。如代码清单7-2所示:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="294dp"android:minHeight="72dp"android:updatePeriodMillis="86400000"android:previewImage="@drawable/preview"android:initialLayout="@layout/example_appwidget"android:configure="com.example.android.ExampleAppWidgetConfigure" android:resizeMode="horizontal|vertical">
</appwidget-provider>

代码清单 7-2

以下是<appwidget-provider>属性的摘要,在这之前最好你已经阅读了第一部分的Widget设计章节:

◆App Widget默认的情况下minWidth和MinHeight属性值指定最小占据的空间,AppWidgets默认是在Home屏幕位置,在其窗口基础上的单元格中有一个明确高度和宽度的网格。如果一个App Widget的最小宽度或高度值不匹配单元格的尺寸,则App Widget尺寸向上舍入到最接近的单元格大小。

注:为了使App Widget更容易移植在不同设备,App Widget的最小尺寸不应大于4×4单元格

◆minResizeWidth和minResizeHeight属性指定App Widget的绝对最小尺寸。这些值应该指定尺寸下,否则应用程序组件将无法辨认或以其他方式使用。在android3.1,允许用户使用这些属性调整控件大小,可能是小于默认尺寸界定的minwidth和minheight属性。

◆updateperiodmillis属性定义,往往在App Widget框架,应从appwidgetprovider请求通过调用onupdate()回调方法更新。实际上不能保证更新的准确性,我们建议尽可能的少更新或者不超过每小时一次,以此来节省电池。你也可以在configuration-some中允许用户调整频率,比如证劵报价机,一些用户可能想要15分钟更新一次,一些则想要每天只更新四次

注:如果该设备是睡着的,而它是一个更新的时间(定义updatePeriodMillis)时,则该设备将被唤醒以执行更新。如果你不超过每小时更新一次,这可能不会对电池寿命造成重大的问题。但是,如果您需要频繁更新或你并不需要更新,而设备是睡着的,你就可以根据报警代替执行,则不会唤醒设备执行更新。要做到这一点,设置一个Intent,当您的AppWidgetProvider收到的报警时,使用AlarmManager。设置报警类型有ELAPSED_REALTIME或RTC,这在收到报警时,该设备被唤醒。然后设置updatePeriodMillis为零(“0”)。

◆initialLayout的属性指向布局资源,它定义了App Widget的布局。

◆在Activity启动时对属性进行配置定义,用户添加App Widget,以便让用户配置App Widget属性。这是可选的。

◆在配置previewImage属性后将指定一个App Widget图标是什么样子,当选择这个App Widget时用户可以进行预览。如果没有提供图标,用户却认为laucher是您的应用程序图标。这个字段对应android:previewImage进行在 <receiver>元素的AndroidManifest.xml文件中。在android3.0引入。

◆在Android 3.0引入,该autoAdvanceViewId属性指定的App Widget子视图的视图ID。

◆在Android 3.1引入,该resizeMode属性指定其中一个可以调整规则的Widget。您可以使用此属性使主屏幕Widget的调整方式,如水平,垂直,或两轴。用户长按一个Widget,会显示其调整的界面,然后拖动水平和/或垂直的控键,改变布局网格的大小。resizemode属性值包括"horizontal", "vertical", 和"none"。两者都有如“horizontal | vertical”。

7.4 创建App Widget布局

你必须为你的App widget定义初始布局,你可以在XML定义并保存在项目的res/layout/目录中。你可以使用下列的View对象来设计你的App widget,但在你开始设计你的App widget之前,请阅读和理解App widget的设计准则。 如果你熟悉XML的布局,创建App widget的布局很简单。然而,你们必须知道App widget的布局都是基于RemoteViews类,它不支持各种布局或view widget。
一个RemoteViews对象支持以下布局类:

FrameLayout

LinearLayout

RelativeLayout

以下View支持widget:

AnalogClock

Button

Chronometer

ImageButton

ImageView

ProgressBar

TextView

ViewFlipper

ListView

GridView

StackView

AdapterViewFlipper

但是这些类的子类却都不支持。

1. 添加边距到App Widgets

widget通常不应该扩展到屏幕边缘,不应与其他widget视图共同刷新,所以你应该在你的widget框中增加边距。自Android 4.0起,App widget提供了widget之间的自动填充框架和App widget的包围盒,以便用户在home屏幕更好的调整其他widget和图标。要获得这种功能,你需要吧应用程序的targetSdkVersion设置为14或更高。
早期版本,编写一个布局很容易,并可以自定义边距,在Android4.0或以上版本并没有额外的边距,步骤如下:
◆设置应用程序的targetsdkversion值为14或更高。
◆创建一个如下布局,引用dimension资源,如代码清单7-3所示:

<FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:padding="@dimen/widget_margin"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:background="@drawable/my_widget_background">…</LinearLayout></FrameLayout>

代码清单 7-3

◆创建两个dimensions 的资源,一个在res /values/提供Android 4.0之前的自定义边距,一个在res/values-v14/没有为Android4.0widgets提供额外的padding:
res/values/dimens.xml:

<dimen name="widget_margin">8dp</dimen>

res/values-v14/dimens.xml:

<dimen name="widget_margin">0dp</dimen>

7.5 使用AppWidgetProvider类

首先,你必须在AndroidManifest<receiver>节点里声明 的AppWidgetProvider类的实现(参见本章的“7.2在Manifest.xml中声明App Widgets” )。

AppWidgetProvider继承broadcastreceiver用来处理App widget广播非常方便。 AppWidgetProvider只接收和App widget相关的事件广播,如App widget进行更新时,相关的App widget进行删除,启用和禁用。这些广播事件发生时,AppWidgetProvider将调用以下的方法:
◆onUpdate()

这种在AppWidgetProviderInfo由updatePeriodMillis属性定义的时间间隔来使AppWidget更新。当用户添加App widget时,这种方法也被调用,所以它应该进行基本的设置,如定义View事件的处理,如果有必要,还应启动临时service。不过,如果你已经声明配置的Activity,当用户添加App widge这种方法则不会调用,而是后续更新调用。配置的Activity完成后,它的作用就是执行首次更新。

◆onAppWidgetOptionsChanged()

当wodget第一次被调整时被调用。你能使用这个回调来显示或隐藏内容。你可以通过getAppWidgetOptions()来获得大小范围,它返回一个Bundle,你可以使用下面String键,来获得值:

AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH—当前宽度的最小值,单位是DP

AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT—当前高度的最小值,单位是DP

AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH—当前宽度的最大值,单位是DP

AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT—当前高度的最大值,单位是DP

Android4.1从在引入这个方法。请注意

◆onDeleted(Context, int[])

每次一个App Widget从App Widget主机中删除时被调用。

◆onEnabled(Context)

首次创建App widget实例时调用。例如,如果用户为同一个App widget添加了两个实例,这也只调用一次。如果你需要打开一个新的数据库或进行其他的设置,那么在这个地方实例是非常好的。

◆onDisabled(Context)

当最后一个App widget的实例时从App widget主机中删除时被调用,使用onDisabled(Context)方法进行清理,比如删除临时数据库。

◆onReceive(Context, Intent)

可以理解为一个通用广播接收接口,上面的每个方法的回调。你通常不需要实现这个方法,因为默认的AppWidgetProvider实现过滤器所有App widget广播,并适当调用以上的方法。

当每个App widget添加到一个主机时,最重要的是AppWidgetProvider onUpdate()方法回调(除非你使用一个配置的Activity)。如果你的App widget接受任何用户交互事件,那么在回调时,你需要注册事件处理器。如果你的App widget不能创建临时文件或数据库,或者执行其他的工作,那就需要清楚,onUpdate()方法,可能是你唯一需要定义的回调方法。例如,如果你想要一个App widget上有一个按钮,当点击时启动一个Activity,你可以这样实现AppWidgetProvider,如代码清单7-4所示:

public class ExampleAppWidgetProvider extends AppWidgetProvider {public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {final int N = appWidgetIds.length;for (int i=0; i<N; i++) {int appWidgetId = appWidgetIds[i];Intent intent = new Intent(context, ExampleActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);views.setOnClickPendingIntent(R.id.button, pendingIntent);appWidgetManager.updateAppWidget(appWidgetId, views);}}
}

代码清单 7-4

上面代码清单7-4中的AppWidgetProvider只定义onupdate()方法,其目的是定义一个PendingIntent启动一个Activity并使用使用setonclickpendingintent(int,pendingintent)附加到App widget按钮。注意,在appWidgetIds中它包括一个循环遍历每个条目,这是一个数组的id标识,确定每个App widget。这样,如果用户创建多个App widget的实例,然后他们都同时更新。然而,只有一个updateperiodmillis时间表将管理所有的App widget。例如,如果更新计划被定义为每两个小时,在第一个后等待一小时在添加第二个实例,那么它们两个都将使用第一个的周期而第二个更新周期会被忽略。读者可以参考ApiDemos\src\com\example\android\apis\appwidget的例子。

AppWidgetProvider就是一个方便的类而已。如果你想直接接收App widget广播,你可以实现自己的BroadcastReceiver或覆盖的onReceive(Context, Intent) 方法。你需要注意以下几个intent:

ACTION_APPWIDGET_UPDATE

ACTION_APPWIDGET_DELETED

ACTION_APPWIDGET_ENABLED

ACTION_APPWIDGET_DISABLED

ACTION_APPWIDGET_OPTIONS_CHANGED

7.6 创建一个App Widget配置的Activity

如果你想要一个用户,当他增加了一个新的App widget时来配置设置,那么你可以创建一个App widget配置Activity。当前的Acitivity将自动启动的App widget的主机,并允许用户在创建时配置App widget的颜色,大小,更新周期或其他功能的设置。 这个配置Activity应该在Android manifest文件中声明是一个标准的Activity。然而,它将通过App widget主机使用ACTION_APPWIDGET_CONFIGURE Action来启动,所以这个Activity需要接收这种Intent。如代码清单7-5所示:

<activity android:name=".ExampleAppWidgetConfigure"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/></intent-filter>
</activity>

代码清单 7-5

此外,Activity必须在AppWidgetProviderInfo XML文件中声明android:configure属性(参见前面小节“添加AppWidgetProviderInfo元数据”)。例如,需要配置的Activity声明如代码清单7-6所示:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"...android:configure="com.example.android.ExampleAppWidgetConfigure" ... >
</appwidget-provider>

代码清单 7-6

注意,这个Activity是声明完全限定的命名空间,因为它是从外部包引用的。
你需要的是启动一个配置Activity。现在你所需要的是实际的Activity。然而,当你实现Activity有两个重要的事情要记住:

◆这个App widget主机调用配置Activity,而配置Activity应该总是返回一个结果码。这个结果码应该包括App widget  ID。

◆当创建App widget时OnUpdate()方法将不会被调用(配置Activity启动时,系统将不发送ACTION_APPWIDGET_UPDATE广播)。

这是配置Activity的职责,它请求从App widget首次创建AppWidgetManager时更新。然而,onUpdate()方法将调用后续更新,它仅在第一次跳过。

请参阅以下的代码片段,看它怎样返回配置和更新的App widget后的结果。

当一个App widget使用配置Activity时,这个Activity配置完成后负责更新App widget。你可以从AppWidgetManager通过请求直接更新。
1. 从通过Intent启动的Activity中获得App widget的ID:

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}

2. 执行你的App widget配置.
3. 当配置完成后,通过调用getInstance(context)获得一个AppWidgetManager实例:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

4. 通过调用updateAppWidget(int,RemoteViews)来使用RemoteViews布局更新App widget:

RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);

5. 最后,创建返回的intent,其设置Activity的结果,并终止该Activity:

Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();

7.7 设置一个预览的图片

Android3.0之后引入了previewImage属性,它指定一个Appwidget缩略图。下面让我们看下代码清单7-7,看看是如何设置的

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"...android:previewImage="@drawable/preview">
</appwidget-provider>

代码清单 7-7

为了帮助您的Appwidget(指定在previewImage领域)创建预览图像,在Android模拟器中包含一个应用程序被称为“Widget Preview”。要创建预览图像,则要启动该应用程序,选择你的应用程序的Appwidget,并设置你希望的预览图像,然后将它保存,并将其放置在你的应用程序的drawable资源下。

本文来自jy02432443,是本人辛辛苦苦一个个字码出来的,转载请保留出处,并保留追究法律责任的权利 QQ78117253

第三部分:Android 应用程序接口指南---第一节:应用程序组件---第七章 App Widgets...相关推荐

  1. 第三部分:Android 应用程序接口指南---第二节:UI---第八章 Toast通知

    第8章 Toast通知 Toast通知是在窗口前面弹出的信息.它只占有信息所需要的空间量,并且用户当前的activity仍然是可见的.可互动的.这种通知自动地淡入和淡出,它不接受交互事件.他相当于一种 ...

  2. 第三部分:Android 应用程序接口指南---第二节:UI---第六章 对话框

    第6章 对话框 一个对话框是一个小窗口,提示用户做出决定或输入额外的信息,一个对话框不填充屏幕并且通常用于在程序运行时中断,然后弹出通知提示用户,从而直接影响到正在运行的程序.图6-1就是对话框的外观 ...

  3. 第三部分:Android 应用程序接口指南---第三节:应用程序资源---第四章 本地化...

    第4章 本地化 Android系统会在很多地区的不同设备上运行.为了能够将应用提供给更多的用户,你的应用应该以不同的方式处理文本.音频文件.数字.货币和图形,以适合于你应用使用的地点. 本文档描述了本 ...

  4. 第三部分:Android 应用程序接口指南---第三节:应用程序资源---第五章 资源类型...

    第5章 资源类型 这一大章节的每个部分描述了一类应用资源的用法,格式和语法.你可以把这些资源放在你的资源目录下(即res/).下面是对每个资源类型的简介: ◆动画资源(Animation Resour ...

  5. 第一集 斗罗世界 第七章

    第一集 斗罗世界 第七章 小舞,你还要啊?(一) "也就是说,在未来获得魂环的时候,尽可能获得类似能力的魂环,不一定要完全一样,但大方向是要类似的,以免出现自身魂环相冲突,反而制约了自身实力 ...

  6. Android 学习之《第一行代码》第6章:adb调试:pemission denied以及模拟器不能获取root权限问题的解决

    问题描述: <第一行代码>第六章用ADB工具打开数据库过程中,cd 命令直接报 permission denied,想着应该是权限不够,于是尝试输入su .sudo.su root.adb ...

  7. 《文明之光 第一册》一一第七章 一个家族的奇迹

    第七章 一个家族的奇迹 文明之光 第一册 文艺复兴 全世界恐怕没有哪个家族(王室除外)比美第奇家族(House of Medici) 更富有传奇色彩了.这个家族曾经是世界上最富有.最有影响力的家族,他 ...

  8. android webview js交互 第一节 (java和js交互)

     转载请注明出处         挺帅的移动开发专栏  http://blog.csdn.net/wangtingshuai/article/details/8631835        在andro ...

  9. 安卓手机python开发环境_使用Python开发Android应用程序:第一节 在手机上配置Python运行环境...

    本节目录: 1.下载和安装 Scripting Layer for Android (SL4A) 2.下载和安装 Python for android 3.第一个HelloWorld程序 1.下载和安 ...

最新文章

  1. 2-3 人工智能需要的基本数学知识|人工智能框架TensorFlow应用实践
  2. Linux vim复制操作
  3. Comparable与Comparator用法详解
  4. 《数据库原理与应用》(第三版)第15章 备份和恢复数据库 基础 习题参考答案
  5. springboot+springcloud相关问题
  6. POJ2752-Seek the Name, Seek the Fame【KMP】
  7. leetcode —— 面试题12. 矩阵中的路径
  8. Java:从 Map 到 HashMap 的一步步实现!
  9. UI素材模板|优秀的后台管理系统UI面板
  10. nginx php-cgi php
  11. python设置tk退出_Tkinter退出按钮
  12. U大师U盘启动盘制作工具(V1.1.0版)——升级U盘
  13. VMware 14 版本激活许可证
  14. 豆瓣小组html模板,用前端的方式打开豆瓣租房小组
  15. 数据结构算法——1006. 线性链表的插入与删除
  16. 深圳中科院计算机研究所,专家人才库数据----中国科学院计算技术研究所
  17. 新技能get!用 Python 高效背单词!
  18. 原创|「肖申克的救赎」观影有感
  19. Sorry, but pdflatex did not succeed
  20. iphone游戏开发_iPhone开发的10个步骤

热门文章

  1. Java字符串处理技巧
  2. linux系统安装后优化
  3. 《再不疯狂,我们就老了》 -- [澳]塞巴斯蒂安·特里
  4. 今年端午节,想回家看看父母...
  5. 说说如何基于 Vue.js 实现表格组件
  6. 一键安装lamp系统
  7. 利用getchar()消除多余字符数据(主要是“回车”)
  8. [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.21
  9. Windows Server 2008 R2 SP1遗忘管理员密码后的解决方案
  10. Ajax应用开发:实践者指南