App Widget对于Android来说是非常强大的。通过它,开发人员可以创建简单的控件,在主屏幕上或在任何程序中提供类似的主机托管功能。在创建一主屏幕App Widget时,您学习了如何创建和配置一个App Widget。这个简单的应用程序插件播放了一个由用户预先设定时间间隔的图像幻灯片。但是,如果用户想改变这个时间间隔?如果他们想暂停幻灯片或立即跳到下一张图片他们该怎么做呢?在本文中,您将学习如何对App Widget增加用户控件来处理这些行为。
为了处理与App Widget的交互,必须执行下面的任务:
1、为每个App Widget控件设置唯一的单击处理器。
2、这个单击处理器向注册接收器发送一个命令
3、处理收到的命令并执行任何必要行动
4、更新App Widget,以反映变化
在这个例子中,我们将修改之前文章所创建的App Widget(图1,顶上的App Widget ),包括一个带有三个控件的按钮栏(图1,底部App Widget)。按钮栏上的每个按钮将执行一项具体的行动,然后点击App Widget的任何地方将隐藏按钮栏。左边的按钮(工具集)将启动配置活动,用户可以改变幻灯片图像转换之间的时间间隔。中间的按钮将暂停或恢复,幻灯片。右侧的按钮,允许用户立即跳到下一张图片。
Figure 1: App Widget的三个不同状态
Working with RemoteViews
一个App Widget使用一种叫做RemoteViews的特殊的显示控件。与普通视图不同的是,设计RemoteViews控件的目的是显示另一个进程中的视图控件的集合。因此,不能简单地添加一个按钮处理程序,因为该代码将在应用程序的进程中运行,而不是在显示RemoteViews对象的进程中(在这种情况下,主屏幕的进程中)。
为了实现RemoteViews控件的用户交互,您必须注册,一个PendingIntent将会被触发,当包含RemoteViews对象的具体视图被点击时。这是通过调用RemoteViews对象的setOnClickPendingIntent()方法来完成的。例如,增加PendingIntent启动活动来配置幻灯片的时间间隔,我们会添加以下代码:
1PendingIntent pendingIntent=PendingIntent.getActivity2(context,0, configIntent,3PendingIntent.FLAG_UPDATE_CURRENT);4remoteView.5setOnClickPendingIntent(R.id.config, pendingIntent);67
Working with PendingIntents
一个PendingIntent基本上是一个包装对象,结合一个带有目标的行动intent,例如startActivity(),或broadcastIntent()。在前面的文章中,我们用PendingIntent,通过警报触发App Widget来改变图像显示。如果你还记得,当不止一个App Widge存在时,intent必须是独一无二的,用于应用程序来区分不同App Widget的具体事例,(见图1)。这种实现是通过包含App Widge的Uri区域标识,让每个App Widget都有自己的时间间隔。
下面的代码使用此相同的方法来创建configIntent的启动时间延迟配置行为。每一个App Widget将推出正确的appWidgetId。
1Intent configIntent=2newIntent(context, ImagesWidgetConfiguration.class);3configIntent.putExtra(4AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);5configIntent.setData(Uri.withAppendedPath(Uri.Parse6(ImagesWidgetProvider.URI_SCHEME+"://widget/id/"),7String.valueOf(appWidgetId)));8
现在,配置按钮可以工作了,我们可以添加其他按钮栏的功能,诸如跳转到下一张图片。为了标记RemoteViews控件跳到下一张图片,我们将需要回放到App Widget来改变状态。
首先,它可能看起来状态信息可以被编码,就像Intent部分被按钮处理程序发送。请记住, App Widget也将定期更新。intent将不会改变,也不会知道新的状态。为了解决这个问题,我们为App Widget创造一个新的action类型称为ACTION_WIDGET_CONTROL和附加命令给intent的Uri。然后,我们在SharedPreferences存储App Widget的状态。在实践中,App Widget的实现通常有足够简单的结构,以便没有明显的用户延迟。
下面的辅助方法演示了PendingIntent的创意,来处理新的动作类型ACTION_WIDGET_CONTROL:
1privatePendingIntent makeControlPendingIntent2(Context context,Stringcommand,intappWidgetId) {3Intent active=newIntent();4active.setAction(ACTION_WIDGET_CONTROL);5active.putExtra(6AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);7Uri data=Uri.withAppendedPath(8Uri.parse(URI_SCHEME+"://widget/id/#"+command),9String.valueOf(appWidgetId));10active.setData(data);11return(PendingIntent.getBroadcast(context,120, active, PendingIntent.FLAG_UPDATE_CURRENT));13}14
在上面的代码块创建了一个新的具有一个ACTION_WIDGET_CONTROL的Intent(是一个字符串)。接着,我们为App Widget的唯一ID设置Intent Extra的值。唯一的Uri被编译,融入所需的命令。这一intent将由App Widget主机是准备播放到Android系统。这将是由同一个广播接收器处理,处理一般的App Widget命令。
App Widget将能够获得这样的广播在他的onReceive()方法:
1elseif(ACTION_WIDGET_CONTROL.equals(action)) {2finalintappWidgetId=intent.getIntExtra(3AppWidgetManager.EXTRA_APPWIDGET_ID,4AppWidgetManager.INVALID_APPWIDGET_ID);5if(appWidgetId !=6AppWidgetManager.INVALID_APPWIDGET_ID) {7this.onHandleAction(8context, appWidgetId, intent.getData());9}10
处理状态
现在你了解用户触发一个Intent对象传递给App Widget,以及它如何被捕获,可以处理的请求操作。包括:
1、获取适当的RemoteViews实例
2、检索和改变其状态
3、将这些变化应用到RemoteViews控件
4、调用updateAppWidget()方法将变化应用到相应的App Widget。
处理这些任务的每个代码在onHandleAction()和updateDisplayState()方法的实现,源代码可以下载此文章。
每次RemoteViews控件更新,是从原来的布局重新创建。然而,现在单击处理程序就可以使用。基于App Widget当前的状态,所需的单击处理程序是以相同的方式添加,就像我们早期添加的配置活动。这些处理程序也可用于review在源代码的updateDisplayState()方法中。
更新布局
为了实现该按钮在整个部件的底部绘图栏的效果,我们启用了两FrameLayout控件,外层FrameLayout -包括整个App Widget-包含ImageView显示和另一个按钮栏FrameLayout。第二个FrameLayout将用于在其父窗口的底部绘制,它包含了三个ImageButton控件的设置,播放/暂停和下一张图片。按钮栏FrameLayout可以通过简单地设置其可见性属性从视图中隐藏了。完整的布局文件(widget.xml)可以在本文提供的示例代码中看到。
更新Android清单文件
最后,该系统将无法知道这样可以处理我们的新的action类型,除非我们更新AndroidManifest.xml文件,包括适当的intent过滤器:
1235678
这种intent过滤器指示应用程序,以观察播放带有action 类型为ACTION_WIDGET_CONTROL的 intent,其的值是“com.mamlambo.ImagesWidget.WIDGET_CONTROL”。
结论
App Widget增加了一个全新的领域,Android的用户体验。这些App Widget不需要是静态的,但可以包含互动功能以及对用户的点击事件作出反应等。在本文中,你学会了如何增加用户互动的Android App Widget。这样做,你学会了如何使用PendingIntent 和RemoteViews交互。最后,你了解了intent机制的限制,以及如何工作,可以围绕创造一个App Widget,而使其主屏幕更舒适。