运行结果:

android天气app界面 安卓天气小部件_xml

android天气app界面 安卓天气小部件_android_02

android天气app界面 安卓天气小部件_action_03






左边的图是将小部件添加到桌面后,google天气中获取数据后显示出来。

中间的图是点击小部件后,显示的透明的Activity,也就是下文就所提到的相应的点击事件。

右边的图是在点击发送按钮后,刷新Widget的结果。使用的刷新方法是下文中提到的直接在外部Activity中刷新。

 

Widget简介

 

桌面部件是一种利用AppWidget框架将应用程序的某个部件放在桌面上,以便于用户快速了解信息以及操作应用程序的桌面组件,如显示天气,日历等等。

要为应用程序定义桌面部件,首先要在应用程序项目的res/xml目录下新建一个XML文件来对桌面部件进行描述,其描述的信息包括了桌面部件的桌面上所占的空间、更新的周期时间以及部件的布局文件。由于在桌面上所有组件的大小均以单元格为单位,所以这里我们要对桌面部件的最小宽度和最小高度进行描述,然后当桌面部件最终被添加到桌面上时,其大小会被设定为最接近的所占单元格数大小。

 

AppWidget框架是通过广播Intent的方式来对桌面部件进行控制的,所以每个桌面部件的XML文件都有一个对应的广播接收器。为了针对桌面部件不同的状态执行不同的操作,AppWidget框架提供了一个集成自BroadcastReceiver的AppWidgetProvider类。这样我们只需要在应用程序中创建一个AppWidgetProvider的子类,然后重新实现不同状态下的回调方法就可以响应AppWidget框架的控制了。

可以在AppWidgetProvider的回调方法onDeleted,onUpdate, onEnabled, onDisabled, onReceive中加入Log信息来查看调用顺序。

 

添加一个Widget到桌面上: 
onEnabled被呼叫:按照说明,当桌面上出现第一个此Widget的实例时,此函数被呼叫。 
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_ENABLED 
onUpdate被呼叫:onUpdate,Count:1,并且待更新的AppWidget数量为1 
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE 

再添加一个Widget到桌面上: 
onUpdate被呼叫:onUpdate,Count:1,并且待更新的AppWidget数量仍然为1,而不是2。 
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE 

从桌面上移除一个Widget: 
onDeleted:每个实例被移除时都会被呼叫 
onReceive,Action:android.appwidget.action.APPWIDGET_DELETED 

再从桌面上移除一个Widget: 
onDeleted:仍然执行 
onReceive,Action:android.appwidget.action.APPWIDGET_DELETED 
onDisabled:因为是最后一个活动的实例被移除了,所以被呼叫。 
onReceive,Action:android.appwidget.action.APPWIDGET_DISABLED

 

刷新AppWidget

1 在onUpdate()中刷新

在上述方法的实现中,如果我们要对已经添加到桌面部件进行修改,如桌面部件的周期性跟新,首先要根据桌面部件的部件文件构造一个RemoteViews对象。RemoteViews是一个描述可在其他进程运行的部件的类,其构造方法需要传入部件的布局文件以及其所在包的包名,构造好了后就可以利用RemoteViews对象对桌面部件进行修改了。桌面部件修改完毕后,最后需要利用一个AppWidgetManager对象调用updateAppWidget方法来传入修改好的RemoteViews对象。

 

2 直接在外部Activity中刷新

btnRefresh.setOnClickListener(new OnClickListener() {                 
                     
                           String value =teInput.getText().toString();
                           RemoteViews appWidgetView = new RemoteViews(SendMsgActivity.this.getPackageName(),R.layout.widget_layout_demo);
                           appWidgetView.setTextViewText(R.id.tv1,value);
                           appWidgetView.setTextViewText(R.id.tv2,value);
                           AppWidgetManager.getInstance(SendMsgActivity.this)
                                  .updateAppWidget(newComponentName(SendMsgActivity.this, AppWidgetDemo.class), appWidgetView);
                     
              });

上述代码可以直接刷新AppWidget的内容,不会触发其onUpdate().

 

相应点击事件

因为onUpdate是每个AppWidget被放置到桌面上时都会被呼叫的函数,所以在此函数中完成事件的关联:

Intent intent = new Intent(context,SendMsgActivity.class);
              PendingIntent pendingIntent =PendingIntent.getActivity(context, 0, intent, 0);
              appWidgetView.setOnClickPendingIntent(R.id.tv1,pendingIntent);

另外要注意此段代码必须要在appWidgetManager.updateAppWidget()之前,否则是不会生效的。 运行后可以点击AppWidget的第一个控件,就能呼叫指定的Activity了。

 



参考资料:

http://developer.android.com/guide/practices/ui_guidelines/widget_design.html

http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout

http://mypyg.iteye.com/blog/930072

http://ssd910.blog.163.com/blog/static/238767972010613257484/