【安卓筆記】Widget

rowandjj發表於2014-12-31
什麼是Widget?
App Widget是android提供的桌面小工具,它能夠嵌入到桌面,並且可以定期更新自己的資料。
如下圖所示:

如何建立Widget?
建立一個Widget需要以下幾個元件:
1AppWidgetProviderInfo:這個類提供了Widget的後設資料,比如Widget的佈局,更新頻率,大小等等。它通常都使用xml定義,位置為res/xml。
2.AppWidgetProvider:這個類是一個廣播接收者,用來接收一些廣播資訊,比如widget是否可用、widget更新、widget被刪除等。通常,我們需要繼承這個類並複寫onXXX等生命週期方法。
3.Widget佈局:建立Widget需要指定其佈局,這個在res/layout下定義即可。
4.AppWidgetManager:這個類可以更新Widget的狀態,並可以獲取已經註冊的AppWidgetProvider的資訊。

建立Widget的步驟:
1.定義一個類繼承AppWidgetProvider:
package com.example.widget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
public class MyWidgetProvider extends AppWidgetProvider
{
	@Override
	public void onEnabled(Context context)
	{
		super.onEnabled(context);
	}
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds)
	{
		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}
	@Override
	public void onDisabled(Context context)
	{
		super.onDisabled(context);
	}
}
2.在res/layout下定義widget的佈局:
比如叫widget_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="2dp"
     >
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
		android:orientation="horizontal"        
        >
        <Button 
            android:id="@+id/btn"  
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="開啟軟體"
            android:textColor="@android:color/black"
            />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="這是一個widget"
            />
    </LinearLayout>
</FrameLayout>
3.在res/xml目錄下建立一個xml資源,定義widget的基本資訊:
比如叫:app_widget_info.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minHeight="50dp"
    android:minWidth="290dp"
    android:updatePeriodMillis="86400000" >
</appwidget-provider>
還有一些其他標籤,用法參見文件。

4.在清單檔案中配置AppWidgetProvider:
<receiver android:name="com.example.widget.MyWidgetProvider" >
            <intent-filter><!--action name是固定的-->
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/app_widget_info" />
</receiver>
至此,Widget建立完成,效果如下:

這時候的button是沒有點選效果的,那麼如何為其增加按鈕點選的響應事件呢?
那就要使用到AppWidgetManager了。
在這之前我們先介紹下Widget的生命週期,可以在上面MyWidgetProvider中打log,通過分析log我們可以得出如下結論:
1.第一個widget被拖到桌面上:onEnabled()--->onUpdate()
2.以後每個widget被拖到桌面上:onUpdate()
3.刪除一個Widget:onDeleted()
4.最後一個widget被刪除:onDeleted()-->onDisabled()
另外,如果你複寫了onReceive方法,那麼onReceive方法是最先執行的(確保要呼叫super.onReceive)。其實我們分析下AppWidgetProvider原始碼就很容易看出來,AppWidgetProvider在onReceive方法中通過判斷action型別,來執行不同的業務方法,而具體的業務方法是由子類來複寫的。

5.新增響應事件
既然每個widget被拖到桌面都會呼叫onUpdate,那麼我們就在這個方法中為按鈕新增監聽:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds)
	{
		Log.d(TAG,"onUpdate...");
		RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context,MainActivity.class),0);
		views.setOnClickPendingIntent(R.id.btn, pendingIntent);
		appWidgetManager.updateAppWidget(appWidgetIds, views);
	}
這裡需要用到AppWidgetManager的updateAppWidget方法,這個方法需要傳入widget的id和RemoteViews。這個RemoteViews很關鍵,我們要為按鈕新增響應事件,就得呼叫這個類的setOnClickPendingIntent方法,當然了,它也提供了很多其他方法,諸如setTextViewText、setProgressBar等,這些方法有個共同點,那就是必須傳入view的id。更多用法請檢視文件。
通過上面的方法,當我們點選按鈕時,就可以開啟主介面了!

widget通常需要配合service使用。因為,widget需要定時更新資訊,所以一個後臺服務必不可少。這時候我們可以再onEnabled中啟動服務,然後在服務中增加一個定時器(Timer或者AlarmManager),定期更新widget,這時候可以通過
AppWidgetManager.getInstance(context);
獲取AppWidgetManager例項。


以上是widget的基本用法,更多用法參見文件。











相關文章