widget初步

来源:互联网 发布:javascript 数组对象 编辑:程序博客网 时间:2024/04/30 07:36

最近项目里用到widget,之前一直没有接触过,正好借此机会学习了,在此,也把自己最近学到的以及自己对widget的理解整理下来,一来可以和大家分享,共同讨论,二来又可以加深自己对新学知识的印象。

AppWidget 就是HomeScreen上显示的小部件,提供直观的交互操作。通过在HomeScreen中长按,在弹出的对话框中选择Widget部件来进行创建,长按部件后并拖动到垃圾箱里进行删除。同一个Widget部件可以同时创建多个。 

AppWidget的实现主要涉及到以下类: 
AppWidgetProvider 
RemoteViews 

AppWidgetManager 


1. 
首先需要提供一个定义了Widget界面布局的XML文件(位于res/layout/..),需要注意的是使用的组件必须是RemoteViews所支持的,目前原生API中支持的组件如下: 
FrameLayout 
LinearLayout 
RelativeLayout 

AnalogClock 
Button 
Chronmeter 
ImageButton 
ImageView 
ProgressBar 

TextView 


*如果使用了除此之外的组件,则在Widget创建时会导致android.view.InflateExceptionn异常。 

之前想要自定义view,结果就很悲剧的没显示出来。。。只能手动绘图再用ImageView加载进去

PS:这就导致有一些功能或样式无法实现,如很基本的list或文本编辑框都是无法直接实现的。如果想自定义Widget中的View的话只能通过修改framework来提供相应组件的支持。 

2. 
然后需要提供一个xml文件来定义Widget的基本属性,放置到res/xml/..目录下。 
如果使用的是Eclipse可按如下操作: 
1) 在res/目录下创建xml/目录 
2)创建xml文件(名字可任意),选择类型为AppWidgetProvider 
3)在弹出的便捷界面进行参数设置 

主要设置的参数如下: 
minWidth: 定义Wdiget组件的宽度 
minHeight: 定义Wdiget组件的高度 
updatePeriodMillis: 更新的时间周期 
initialLayout: Widget的布局文件 
configure: 如果需要在启动前先启动一个Activity进行设置,在这里给出Activity的完整类名(后面会说到,与一般Activity的实现有些许差别) 
  
3. 
xml都定义好后,接下来就是创建一个继承自AppWidgetProvider的子类,AppWidgetProvider实际上就是一个BroadcastReceiver(查看源码可知AppWidgetProvider类继承自BroadcastReceiver),里面提供了以下函数: 
onReceive(Context, Intent) 
onUpdate(Context , AppWidgetManager, int[] appWidgetIds) 
onEnabled(Context) 
onDeleted(Context, int[] appWidgetIds) 
onDisabled(Context) 

可通过重写以上函数来监听Widget状态的变化并进行相应的处理。 

4、由于AppWidgetProvider继承了BroadcastReceiver,所以需要在AndroidManifest.xml中注册receiver:

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


 

下面是完整的一个widget demo:显示一个imageview+三个textview

1、在新建的工程目录layout下新建:widget_worldclock.xml,

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="180dp"    android:layout_height="wrap_content"    android:orientation="horizontal"     android:background="@drawable/widget_worldclock_bg">            <ImageView         android:id="@+id/widget_clock"        android:src="@drawable/clockgoog_dial"        android:layout_width="80dp"        android:layout_height="80dp"            />        <LinearLayout        android:id="@+id/widget_citytime"        android:layout_width="90dp"        android:layout_height="wrap_content"        android:layout_marginLeft="10dp"        android:orientation="vertical"        android:layout_gravity="center" >        <TextView             android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="city"            android:layout_gravity="center"                       />        <TextView             android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="time"            android:layout_gravity="center"/>        <TextView             android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="date"            android:layout_gravity="center"/>    </LinearLayout>   </LinearLayout>
2、在工程目录下新建XML文件夹,在该文件夹下面新建worldclock_widgetprovider.xml

<appwidget-provider         xmlns:android="http://schemas.android.com/apk/res/android"    android:minWidth="110dip"    android:minHeight="40dip"    android:updatePeriodMillis="0"    android:initialLayout="@layout/worldclock_widget"    android:previewImage="@drawable/clockgoog_dial"        ></appwidget-provider>
需要说明的是,根节点<appwidget-provider>是必须的!
其中initialLaout指明widget加载到homescreen时的布局,就是刚刚在第一步里写的布局

previewImage为组件里的预览图片,自己指定。

3、src下新建java文件,WorldClockProvider.java,该类要继承AppWidgetProvider

package com.example.worldclock;import android.appwidget.AppWidgetManager;import android.appwidget.AppWidgetProvider;import android.content.Context;import android.content.Intent;public class WorldClockProvider extends AppWidgetProvider {//当该类型的AppWidget每次被删除时,调用此方法    @Override    public void onDeleted(Context context, int[] appWidgetIds) {        // TODO Auto-generated method stub        System.out.println("appwidget--->onDeleted()");        super.onDeleted(context, appWidgetIds);    }    //当该类型的窗口小部件(AppWidget)全被删除时,调用此方法    @Override    public void onDisabled(Context context) {        // TODO Auto-generated method stub        System.out.println("appwidget--->onDisabled()");        super.onDisabled(context);    }    //当第一次创建该类型的AppWidget时,调用此方法    @Override    public void onEnabled(Context context) {        // TODO Auto-generated method stub        System.out.println("appwidget--->onEnabled()");        super.onEnabled(context);    }    //广播接受者方法,用来接受广播消息    @Override    public void onReceive(Context context, Intent intent) {        // TODO Auto-generated method stub        System.out.println("appwidget--->onReceive()");        super.onReceive(context, intent);    }    //每次创建该类型的AppWidget都会调用此方法,通常来说我们需要在该方法里为该AppWidget指定    //RemoteViews对象。    @Override    public void onUpdate(Context context, AppWidgetManager appWidgetManager,            int[] appWidgetIds) {        // TODO Auto-generated method stub        System.out.println("appwidget--->onUpdate()");        super.onUpdate(context, appWidgetManager, appWidgetIds);    }    }

4、注册广播:

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


 

完毕,运行。公司电脑上没装截图工具,就不上运行截图啦,附件里资源文件和背景图

有什么问题欢迎交流o(∩∩)o...


原创粉丝点击