Android桌面小部件AppWidget開發
在Android我們經常可以看到各種桌面小部件,比如時鐘、天氣、音樂播放器等等。我們可以使用AppWidgetProvider來實現小部件的開發。
AppWidgetProvider是Android中提供的用于實現桌面小工具的類,其本質是一個廣播,即BroadcastReceiver。
開發一個桌面小部件的步驟:
一、自定義小部件界面
在res/layout/下新建一個布局文件,名稱和內容自定義,看你想把小工具做成什么樣。需要注意的是系統默認的小工具布局中只支持以下這些標簽,如果用了列表以外的標簽,會導致小工具加載錯誤:
- FrameLayout、LinearLayout、RelativeLayout
- TextClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView
比如,我們創建了一個名為widget_layout.xml的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/doge_imageView"
android:layout_width="110dp"
android:layout_height="110dp"
android:src="@drawable/doge" />
</LinearLayout>
二、定義小部件配置信息
定義小部件的配置信息需要在res目錄下新建一個xml目錄,然后在res/xml/目錄下創建一個配置文件,配置文件名稱隨意。新建app_widget_provider_info.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_layout"
android:minHeight="110dp"
android:minWidth="110dp"
android:previewImage="@drawable/doge"
android:updatePeriodMillis="864000" />
上面的參數意義很明確,initialLayout指小部件的初始化布局,一般與最終布局相同;minHeight和minWidth定義了小部件的最小寬高,與小部件所占網格大小有關;previewImage可以指定在添加小部件時看到的預覽圖;updatePeriodMillis指定了小部件的自動更新周期,單位為毫秒。
其中minHeight和minWidth的定義可以參考官方文檔:https://developer.android.com/guide/practices/ui_guidelines/widget_design.html#design
小部件最小寬高選取.png
三、定義小部件類,繼承自AppWidgetProvider
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;
import android.widget.Toast;
/**
* @author zhengxuze
* @date 2017/1/10 create
*/
public class TestWidgetProvider extends AppWidgetProvider {
public static final String CLICK_ACTION = "com.seewo.appwidgettest.action.CLICK"; // 點擊事件的廣播ACTION
/**
* 每次窗口小部件被更新都調用一次該方法
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent intent = new Intent(CLICK_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, R.id.doge_imageView, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.doge_imageView, pendingIntent);
for (int appWidgetId : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
/**
* 接收窗口小部件點擊時發送的廣播
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (CLICK_ACTION.equals(intent.getAction())) {
Toast.makeText(context, "hello dog!", Toast.LENGTH_SHORT).show();
}
}
/**
* 每刪除一次窗口小部件就調用一次
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
/**
* 當最后一個該窗口小部件刪除時調用該方法
*/
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}
/**
* 當該窗口小部件第一次添加到桌面時調用該方法
*/
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
/**
* 當小部件大小改變時
*/
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
/**
* 當小部件從備份恢復時調用該方法
*/
@Override
public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
super.onRestored(context, oldWidgetIds, newWidgetIds);
}
}
四、在AndroidManifest.xml中聲明小部件
<receiver android:name=".TestWidgetProvider">
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/app_widget_provider_info" />
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.seewo.homewidgets.action.CLICK" />
</intent-filter>
</receiver>
OK,小部件完成了,運行一下看看效果: