Android开发Widget之入门篇

一. Widget介绍: 

       Widget是窗口小部件的意思,比如时间Widget,日历Widget等,可以显示一些信息,或者点击进入一个程序。比如下图的时间Widget:

      

     下面带大家做一个很简单的Widget,点击一个按钮让按钮的文字发生变化,了解下流程。

二.Widget案例演示:

    1.我们先建一个widget_layout.xml文件作为widget的布局,就是桌面上显示的布局。在这里只显示一个按钮。 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/btnSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="点击" >
    </Button>

</RelativeLayout>

    2.我们在res目录下新建一个xml目录,在里面新建一个 widget_config.xml文件,这个文件顾名思义是widget的配置文件,详细的看代码注释。

    

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
   
    android:minHeight="40dp"
    android:minWidth="180dp"
    android:previewImage="@drawable/ic_launcher"
    android:updatePeriodMillis="1000"
    android:initialLayout="@layout/widget_layout"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen|keyguard" >

    <!--
        计算宽高尺寸的公式: (70*n)-30  n为部件所需的大小(占几格)   当前的就是  3X1  
        minWidth            widget的最小宽度
        minHeight           widget的最小高度
        previewImage        选择部件时 展示的图标    
        updatePeriodMillis  更新时间间隔  
        initialLayout       布局文件  
        resizeMode          表示支持的模式,这里支持水平和垂直    
        widgetCategory="keyguard|home_screen"   表示widget可添加的位置 锁屏界面|桌面  
    -->

</appwidget-provider>
   3.开始编写代码。我们新建一个 ClickAppWidget继承自 AppWidgetProvider,如果你看 AppWidgetProvider的源码会发现它继承自BroadcastReceiver。

public class AppWidgetProvider extends BroadcastReceiver {
    /**
     * Constructor to initialize AppWidgetProvider.
     */
    public AppWidgetProvider() {
    }
   。。。。。。

     我们重写它的onDeleted,onDisabled,onEnabled,onUpdate和onReceive方法。在什么时候调用这些方法代码里都标明了,这里只重点说下onReceive和onUpdate方法。

   onReceive方法接受广播事件,可以在这里更新RemoteViews,从而更新widget。先获取RemoteViews实例, new RemoteViews()接受两个参数,一个是应用包名,一个是widget的布局文件。然后通过setTextViewText(R.id.btnSend, "点击成功")设置按钮的值,第一个参数是控件的id,第二个参数是设置内容。如果你的布局有ImageView,你可以调用setImageViewResource(viewId, srcId)设置图片。之后通过获取widget的管理者AppWidgetManager,可以看到这里是单例模式,再通过AppWidgetManager实例获取该应用的所有appWidgetIds,以数组形式返回,最终调用updateAppWidget方法,传入appWidgetIds和remoteViews两个参数就可以了。

  onUpdate方法是在到达xml配置文件里 指定的更新时间或者当用户向桌面添加Widget时就被调用,所以它比onReceive方法先执行,这里我们构建了一个Intent对象,设置一个action为click,然后构建一个创建广播的PendingIntent对象,获得RemoteViews实例,调用setOnClickPendingIntent方法即可,当点击这个按钮时就会发送广播。

   具体的代码就贴在下面:

     

public class ClickAppWidget extends AppWidgetProvider {
	private static final String TAG = "ClickAppWidget";
	
	// 删除widget的时候调用
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		Log.i(TAG, "onDeleted");
		super.onDeleted(context, appWidgetIds);
	}

	// 当最后一个widget被删除时调用
	@Override
	public void onDisabled(Context context) {
		Log.i(TAG, "onDisabled");
		super.onDisabled(context);
	}

	// widget第一次被添加到桌面的时候调用
	@Override
	public void onEnabled(Context context) {
		Log.i(TAG, "onEnabled");
		super.onEnabled(context);
	}

	// 接受广播事件,接受一次就调用一次,和普通广播用法一样
	@Override
	public void onReceive(Context context, Intent intent) {

		if (intent.getAction().equals("click")) {
			Log.i(TAG, "onReceive");

		    // 获得该widget的远程视图实例
			RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
			
			remoteViews.setTextViewText(R.id.btnSend, "点击成功");
			   
			AppWidgetManager mWidgetManager = AppWidgetManager.getInstance(context);
			//获得该应用的所有appWidgetIds
			int[] appWidgetIds = mWidgetManager.getAppWidgetIds(new ComponentName(context,ClickAppWidget.class));
			mWidgetManager.updateAppWidget(appWidgetIds, remoteViews);

		}

		super.onReceive(context, intent);
	}
 	/**
	 * 到达xml配置文件里 指定的更新时间或者当用户向桌面添加Widget时就被调用
	 * @param AppWidgetManager  AppWidget的管理器          
	 * @param appWidgetIds      桌面上 所有的widget都会被分配一个唯一的ID,存在数组里           
	 * */
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		// 创建一个Intent,设定action为click
		Intent intent  = new Intent("click");

		// 设置pendingIntent的作用
		PendingIntent mpendingIntent = PendingIntent.getBroadcast(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);

		//  获得该widget的远程视图实例
		RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
		
		//  设定点击事件
		remoteViews.setOnClickPendingIntent(R.id.btnSend, mpendingIntent);

		//  调用updateAppWidget方法更新Appwidget
		appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
                 
	}
}
   4.最后要在Manifest里添加如下代码   

 <receiver android:name="ClickAppWidget" >
            <intent-filter>
                <action android:name="click" >
                </action>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" >
                </action>
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_config" />
        </receiver>
   

       action里的值android.appwidget.action.APPWIDGET_UPDATE是默认的,meta-data里的name也是默认值,resource的引用的是之前新建的widget配置文件。

 三.结果展示

       我们运行应用后,点添加小工具就可以把widget放到桌面上。

        点击之前和点击之后,widget发生了变化

                 

     

   

     附上Demo下载地址:点击打开链接

      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章