在widget中一样可以使用ListView,GridView等来显式集合形式的数据,而且放置好的widget如果设置了resizeMode属性,还可以在页面上自由缩放以显式更多的内容。

本例将在页面上使用一个带ListView的widget去显式手机上媒体库中的文件(图片或者视频)。

需要使用的文件分析:

1. 描述widget本身的布局文件,置于res/layout文件夹下的xml文件,里面会使用一个ListView以列表的形式来显式手机中的图片或者视频

2.为 widget中的ListView提供ListView中条目的布局文件

3. 描述widget的元数据文件。这个元文件中增加resizeMode属性用来缩放widget大小,增加configure属性用来制定一个Activity,该Activity会在一个widget放置到页面前的一瞬间被打开(通过intent),然后对widget进行相应的设置,设置完毕后利用setResult(resultcode,intent)的方式来结束这个设置Activity。一旦该Activity结束,widget会出现在页面上。这个设置Activity有一定的特殊性,所以在AndroidManifest文件中注册的时候必须声明<intent-flter>,且有特定的action内容。否则这个Activity不能创建,而且widge也不能创建。

注意:同一个布局文件和元数据文件描述的widget可以被反复多次的拖拽到页面上。而每一次增加的widget都是一个独立的新的widget,都会有一个属于自己的id号。元数据描述文件会声明自定义的AppWidgetProvider,这个AppWidgetProvider只有一份,所以在它onUpdate方法中可能需要一次对多个widget进行内容的刷新。除非你确定用户确实只会添加一个widget到页面上。

4. 重写AppWidgetProvider中的onUpdate方法(如果有设置Activity,则第一次创建widget的时候,不会回调onUpdate方法。在元数据的刷新间隔时间到或者利用AppWidgetManager的显示刷新方法时,该方法会被回调)、onEnable(与该AppWidgetProvider相关的第一个widget被创建的时候会被回调,此时,如果有为widget服务的Service,应该在该方法中启动)、onDisable(与该AppWidgetProvider相关的最后一个widget被删除的时候会被回调,此时,如果有为widget服务的Service,应该在该方法中停止)、onDelete(与该AppWidgetProvider相关的widget有一个被删除的时候会被回调,此时如果有相应于该widget绑定的内容,应该在该方法中解除)

5. 在普通界面上使用ListView的时候要提供一个adapter,来绑定和适配数据源中的数据到ListView的一个个条目中。填充widget的ListView时,需要使用一个RemoteViewsService。利用RemoteViews的setRemoteAdapter方法将widget中的ListView与RemoteViewsService进行绑定(这里的绑定不是使用RemoteViewsService的一个实例,而是使用一个激活RemoteViewsService的intent)。与实现adpater需要重写BaseAdapter的若干方法一样,在RemoteViewsService中,需要提供一个RemoteViewsFactory接口的实现。

6. 在AndroidManifest文件中,对设置Activity,AppWidgetProvider和RemoteViewsService进行注册。因为这三个组件都是为widget服务的,因此注册的时候需要添加额外的节点来做额外的说明

完整的代码和代码注解见下篇