android widget的研究(一)

来源:互联网 发布:王家林 知乎 编辑:程序博客网 时间:2024/05/22 14:28

新进了一个项目组, 有个需求是要求在桌面上有个widget直接提用户操作,而不必麻烦每次用户进入应用去设置某些东西.!

关于如何订制widget, 官方文档的位置:/guide/topics/appwidgets/index.html

一:什么是app widget?

官方的解释翻译来就是:  ()窗口小部件(Widget)是微小的应用程序视图,可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新。你可以通过一个App Widget provider来发布一个Widget。可以容纳其它App Widget的应用程序组件被称为App Widget宿主。

二:如何订制自己的widget.?

订制自己的widget很容易-----

1:在AndroidManifest.xml中配置我们的Widget, 从官方文档我得知其实所谓widget其实就是一个BroadcastReceiver, 而我们所继承的AppWidgetProvider继承了BroadcastReceiver,所以我更加确信了它就是一个广播接受者

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

2: 添加AppWidgetIInfo MetaDate(元数据)

在/res/xml文件夹下新建一个widget_info.xml文件, 取这个名字是因为我在receiver中配置<meta-data>的时候就是写的widget_info, 取什么名字都是可以的, 只是<meta-data>的android:resource属性相应的引用就可以了!

<?xml version="1.0" encoding="UTF-8"?><appwidget-provider    android:minWidth="294dp"     android:minHeight="72dip"     android:updatePeriodMillis="600000"     android:initialLayout="@layout/my_widget"    xmlns:android="http://schemas.android.com/apk/res/android" />
关于<appwidget-provider>的一些属性设置, 不过多的解释了, 网上一搜一堆, 不过个人还是推荐看官方文档, 说的已经够详细了, 例如这个最小的宽和高怎么算之类的都有

3: 为widget创建layout, 这里在/res/layout文件夹下创建my_widget.xml, 与上面的保持一致

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="294dp"android:layout_height="72dp" android:background="@drawable/widget_shape"android:gravity="left|center_vertical">        <Button android:layout_width="wrap_content" android:text="widget_button" android:id="@+id/button"        android:layout_weight="1" android:textAppearance="?android:attr/textAppearanceLarge"        android:layout_height="fill_parent" android:gravity="left" /><TextView android:layout_width="wrap_content" android:id="@+id/tvName"android:textAppearance="?android:attr/textAppearanceLarge"android:layout_height="fill_parent" android:gravity="left"></TextView></LinearLayout>

注意: 这里我自己给布局加了个背景, 而这个背景是一个渐变颜色, 是自己在/drawbale文件夹下创建了一个widge_shape.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">     <gradient android:startColor="#FFFF0000" android:endColor="#80FF00FF"             android:angle="270"/>     <padding android:left="50dp" android:top="20dp"             android:right="7dp" android:bottom="7dp" />     <corners android:radius="8dp" />     </shape> 

4: 创建MyWidget类

public class MyWidget extends AppWidgetProvider {@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.my_widget);        String name = "my first widget";                remoteView.setTextViewText(R.id.tvName, name);        appWidgetManager.updateAppWidget(appWidgetIds, remoteView);//super.onUpdate(context, appWidgetManager, appWidgetIds);}}
这里没有调用super.onUpdate()是因为我跟源码进去看了, 父类的这个方法是个空实现, 所以没必要调用

做到这里的时候, 被button的点击事件卡了一下, broadcastReceiver是不能像Activity那样获取到按钮并且为其设置onClick事件的, 也无法在xml中为Button设置android:onClick属性! 我很着急, 于是我静下心来继续读文档,  发现文档上有教阿, 所以在资料甚少的时候, 挖掘官方文档绝对是正解!

文档中点击的时候是去打开一个Activity, 而我这里是做demo,只想它弹一个Toast就够了, 所以我选择调用一个服务!

在onUpdate中添加如下代码:

Intent intent = new Intent(context, MyService.class);        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);        remoteView.setOnClickPendingIntent(R.id.button, pendingIntent);

我没有跟这个setOnClickPendingIntent的源码, 因为我猜也猜的出来这个方法就是让你去指定widget中某个控件的点击事件,  我在想, 这个RemoteViews会提供这个方法的原因是我们无法像在Activity中那样去指定点击事件, 如果没有这个API去指定, 那widget中的按钮就将无法点击(当然google早考虑到了!)

至于Service的代码就不贴了, 里面就一句代码:Toast.make().show();而已!

说一下:如果你向我上面没有什么特殊需求,那么重写Service的onCreate()方法就可以了, 但是当我们用PendingIntent去让别人启服务的时需要用到Intent的话, 到底是该重写onStart()还是onBind()呢.?   答案是应该重写onStart方法,  因为在官方文档PendingIntent.getService()处该方法的描述是:

Retrieve a PendingIntent that will start a service, like calling Context.startService().The start arguments given to the service will come from the extras of the Intent.


文档上还说可以创建配置widget的Activity, 可以从配置Activity中更新widget等.  这次就研究到这里, 基本上有这类需求的童鞋应该够用了! 如果满足不了的话自己读读文档应该能出来,  懒得读的话就期待我下一篇研究widget的文章


原创粉丝点击