因爲項目中需要用到widget,所以在這裏大致記錄一下widget的使用流程。因爲沒有深入的研究,所以僅僅是做一個大概的解析,因爲需求簡單,這裏就不介紹RemoteViewService和RemoteViewFactory了,如果需要的不要浪費時間看下去,抱歉各位。widget也叫小部件,是一個微型視圖,其實在手機launcher中的表就是個widget。在開始流程之前需要明白兩個概念:
AppWidgetProviderInfo
描述小部件的元數據元素,包括描述了部件的佈局和更新頻率,以及AppWidgetProvider的信息
AppWidgetProvider
基於廣播事件,,在這裏可以對widget進行一些操作,包括widget的啓用,更新,刪除等操作。因爲繼承自BroadcastReceiver,因此也可以根據最基本的廣播操作來進行事件的處理。
接下來就是開始創建widget,其實過程比較簡單,studio提供了很多幫助:
在這裏直接創建widget,填寫細節之後,就會生成一個繼承自AppWidgetProvider的類,
public class MyWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
//在這裏進行部件的更新。需要怎樣操控部件都可以再這裏通過RemoteViews實現。
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//這裏會遍歷所有的部件,然後都進行更新。
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
// 當widget被創建的時候調用。
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
//這裏可以接收自定義的一些廣播,進行處理。
}
}
同時在androidManifest文件中也會生成MyWidget的註冊內容
<receiver
android:name=".widget.MyWidget"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- 在這裏還可以添加其他自定義的廣播 -->
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<!-- widget的配置信息文件 -->
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/new_app_widget_info" />
</receiver>
其中name屬性表明類名,intent-filter表示的是接收的廣播action,meta中的屬性name表示meta-data的名稱,這裏必須是android.appwidget.provider, resource這裏是表示資源文件的目錄。接下來看資源文件:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/new_app_widget"
android:initialLayout="@layout/new_app_widget"
android:minHeight="170dp"
android:minWidth="250dp"
android:previewImage="@drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"></appwidget-provider>
initialkeyguardlayout表示了一個資源文件,在widget創建的時候可以立刻出現。4.2以後引入的。
initialLayout 表示了widget的資源文件。
minHeight和minWidth定義了widget的最小高和寬,低於這個值widget不可以用。
previewImage這個就是一個預覽圖的效果。就像app的桌面logo,默認是applogo。
resizeMode:指定widget大小在哪個方向調整。
updatePerionMillis:這個只的是部件的更新頻率,最小是半小時,設置的很小也會默認爲半小時。
widgetCategory:表示部件是否可以顯示在主屏上,默認home_screen,還有power屬性。
到這裏就可以通過new_app_widget這個佈局文件來寫小部件的佈局了。需要注意的是這個佈局文件支持的控件是有限制的, 首先自定義的控件不支持, 支持的佈局控件如下:
佈局:FrameLayout,RelativeLayout,Linearlayout,GridLayout
控件:Button,ImageButton, ImageView,TextView,ListView,GridView,AnalogClock,Progressbar,ViewFlpper,StackView
更新部件的功能都是通過RemoteView來實現的,至於怎樣更新可以根據自己的需求來定。如果用到listview,gridview等佈局可以通過RemoteviewService來實現這個部件的更新,在我的項目裏比較簡單,直接通過啓動一個service進行來更新:在MyWidget中的onenable中通過啓動一個service來實現更新,
private void updateWidget(Context context, WeatherWrap weatherWrap) {
if (weatherWrap == null) {
return;
}
ComponentName componentName = new ComponentName(context, WeatherWidget.class);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
remoteViews.setTextViewText(R.id.temperature, weatherWrap.getNow().getTemp()+"°C");
remoteViews.setTextViewText(R.id.weather_status, DBHelper.getInstance().getWeatherTypeByCode(
weatherWrap.getNow().getWeatherType()));
remoteViews.setTextViewText(R.id.city, weatherWrap.getRegion());
remoteViews.setTextViewText(R.id.air_quality, weatherWrap.getAqi().getAqi() + " "
+ weatherWrap.getAqi().getQuality());
if (weatherWrap.getSuggestion().getDressing() != null) {
remoteViews.setTextViewText(R.id.clothing_index, weatherWrap.getSuggestion().getDressing().getBrief());
}
remoteViews.setTextViewText(R.id.humidity, weatherWrap.getNow().getHumidity() + "%");
if(weatherWrap.getSuggestion().getHongfans() != null){
remoteViews.setTextViewText(R.id.env_status,weatherWrap.getSuggestion().getHongfans().getDetails());
}
remoteViews.setImageViewResource(R.id.weather_bg, Utils.weatherCode2BG(weatherWrap.getNow().getWeatherType()));
//在這裏添加一個點擊事件,當點擊id爲city的按鈕會跳轉到制定activity
Intent intent = new Intent(context, WeatherActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.city, pendingIntent);
AppWidgetManager awm = AppWidgetManager.getInstance(context.getApplicationContext());
awm.updateAppWidget(componentName, remoteViews);
}
可以看到remoteVIew的設置控件內容的方式,以及點擊跳轉的方式。最後都需要通過AppWidgetManager來進行更新。在MyWidget文件的updateAppWidget()函數中也需要添加好更新widget的方法。至於具體的更新方式要根據自己的項目需求而定。