android widget 開發

   因爲項目中需要用到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的方法。至於具體的更新方式要根據自己的項目需求而定。

    

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