一. 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下載地址:點擊打開鏈接