Android Tutorial 第五堂(3)設計小工具元件 - AppWidget
專欄作者新書出版:Android App程式開發剖析 第三版(適用Android 8 Oreo與Android Studio 3) Android Tutorial 第五堂(2)系統通知服務 – Notification << 前情 一般個人電腦或行動裝置的作業系統,可以在桌面上放置應用程式的捷徑,使用明顯的圖示和應用程式的名稱,讓使用者在桌面上直接啟動常用的應用程式。一些使用者經常操作的功能,例如開啟或關閉裝置的網路或藍牙設備,如果可以不用啟動這些設定的應用程式,使用者就可以在桌面上直接操作這些功能,那應該會比較方便一些。 Android平台提供一種特別的元件「AppWidget」,它可以讓使用者在桌面上直接瀏覽資料,或是執行一些簡單的操作。例如在桌面上顯示時間、行事曆或氣候資訊,這種元件通常會把它稱為「小工具」元件。 這一章介紹設計AppWidget元件的作法,它的設計方式跟其它元件很不一樣。完成這一章的工作以後,為記事應用程式加入新的小工具元件。使用者在畫面長按以後,Android會開啟這樣的畫面,選擇「小工具」: 在選擇小工具的畫面,找到為記事應用應用程式設計好的元件,長按以後把它放到畫面指定的位置: 決定小工具的位置以後,元件自動開啟選擇記事的畫面,選擇其中一個記事項目: 畫面上就會放置一個顯示記事標題的小工具元件: 依照同樣的步驟,可以在畫面加入其它顯示記事標題的小工具: 17-1 加入小工具元件現在開始為記事應用程式加入小工具元件。啟動Android Studio與記事應用程式以後,在「app」目錄上按滑鼠右鍵 -> 選擇「New -> Widget -> AppWidget」,依照下列的說明輸入需要的資訊:
完成後選擇「Finish」按鈕: Android Studio會建立許多小工具元件需要的程式碼與設定檔:
實作小工具設定元件使用者選擇記事小工具以後,必須先啟動選擇記事項目元件。小工具元件在專用的設定檔可以設定這個功能,開啟「res/xml/itemappwidget_info.xml」,檢視裡面的內容: <?xml version="1.0" encoding="utf-8"?> <!-- android:previewImage:縮圖 android:initialLayout:小工具元件使用的畫面資源 android:configure:小工具設定元件類別 --> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="250dp" android:minHeight="40dp" android:updatePeriodMillis="86400000" android:previewImage="@drawable/example_appwidget_preview" android:initialLayout="@layout/item_app_widget" android:configure="net.macdidi.myandroidtutorial.ItemAppWidgetConfigureActivity" android:widgetCategory="home_screen" android:initialKeyguardLayout="@layout/item_app_widget"></appwidget-provider> Android Studio會自動產生預設的設定元件與畫面資源,這個設定元件可以重複使用主畫面元件的畫面資源,所以刪除在「res/layout」下的「itemappwidget_configure.xml」。接下來開啟「ItemAppWidgetConfigureActivity.java」,修改類別中的欄位宣告: int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; private static final String PREFS_NAME = "net.macdidi.myandroidtutorial.ItemAppWidget"; private static final String PREF_PREFIX_KEY = "appwidget_"; // 選擇小工具使用的記事項目 private ListView item_list; private ItemAdapter itemAdapter; private List<Item> items; private ItemDAO itemDAO; 同樣在「ItemAppWidgetConfigureActivity.java」,加入下列的方法宣告: // 選擇記事項目 AdapterView.OnItemClickListener itemListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Context context = ItemAppWidgetConfigureActivity.this; // 讀取與儲存選擇的記事物件 Item item = itemAdapter.getItem(position); saveItemPref(context, mAppWidgetId, item.getId()); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ItemAppWidget.updateAppWidget( context, appWidgetManager, mAppWidgetId); Intent resultValue = new Intent(); resultValue.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish(); } }; // 儲存選擇的記事編號 static void saveItemPref(Context context, int appWidgetId, long id) { SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit(); prefs.putLong(PREF_PREFIX_KEY + appWidgetId, id); prefs.commit(); } // 讀取記事編號 static long loadItemPref(Context context, int appWidgetId) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0); long idValue = prefs.getLong(PREF_PREFIX_KEY + appWidgetId, 0); return idValue; } // 刪除記事編號 static void deleteItemPref(Context context, int appWidgetId) { SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit(); prefs.remove(PREF_PREFIX_KEY + appWidgetId); prefs.commit(); } 同樣在「ItemAppWidgetConfigureActivity.java」,找到「onCreate」方法,依照下面的內容修改程式碼: @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setResult(RESULT_CANCELED); // 改為使用應用程式主畫面 setContentView(R.layout.activity_main); // 建立與設定選擇小工具使用的記事項目需要的物件 item_list = (ListView)findViewById(R.id.item_list); itemDAO = new ItemDAO(getApplicationContext()); items = itemDAO.getAll(); itemAdapter = new ItemAdapter(this, R.layout.single_item, items); item_list.setAdapter(itemAdapter); item_list.setOnItemClickListener(itemListener); Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { mAppWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { finish(); return; } } 完成需要的程式碼以後,類別中有許多預設的內容已經不會用到,建議刪除它們。 實作小工具元件接下來修改預設的小工具元件類別與畫面資源。開啟「res/layout/itemappwidget.xml」,這是小工具元件使用的畫面資源,決定小工具在畫面上的樣子。依照下面的內容修改它的設定: <!-- 修改背景 --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/widget_margin" android:background="@drawable/item_drawable"> <!-- 修改文字、大小、顏色與刪除背景 --> <TextView android:id="@+id/appwidget_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/app_name" android:textColor="#000000" android:textSize="16sp" android:textStyle="bold|italic" android:layout_margin="8dp" android:contentDescription="@string/app_name" /> </RelativeLayout> 開啟小工具元件類別「ItemAppWidget.java」,找到「onDeleted」方法,依照下面的內容修改程式碼: @Override public void onDeleted(Context context, int[] appWidgetIds) { final int N = appWidgetIds.length; for (int i = 0; i < N; i++) { // 刪除小工具已經儲存的記事編號 ItemAppWidgetConfigureActivity.deleteItemPref( context, appWidgetIds[i]); } } 同樣在「ItemAppWidget.java」,找到「updateAppWidget」方法,依照下面的內容修改程式碼: static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { // 讀取小工具儲存的記事編號 long id = ItemAppWidgetConfigureActivity.loadItemPref( context, appWidgetId); // 建立小工具畫面元件 RemoteViews views = new RemoteViews( context.getPackageName(), R.layout.item_app_widget); // 讀取指定編號的記事物件 ItemDAO itemDAO = new ItemDAO(context.getApplicationContext()); Item item = itemDAO.get(id); // 設定小工具畫面顯示記事標題 views.setTextViewText(R.id.appwidget_text, item != null ? item.getTitle() : "NA"); // 點選小工具畫面的記事標題後,啟動記事應用程式 Intent intent = new Intent(context, MainActivity.class); PendingIntent pending = PendingIntent.getActivity( context, 0, intent, 0); views.setOnClickPendingIntent(R.id.appwidget_text, pending); // 更新小工具 appWidgetManager.updateAppWidget(appWidgetId, views); } 小工具與設定元件設定最後記得要在應用程式設定檔中,使用「receiver」標籤為小工具元件加入需要的設定。小工具設定元件也需要使用「activity」加入必要的設定。開啟「AndroidManifest.xml」檢視裡面設定的內容: <!-- 小工具元件 --> <receiver android:name=".ItemAppWidget" > <!-- 一定要加入這個Action名稱的設定 --> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <!-- 使用android:resource指定小工具專用設定檔的資源名稱 --> <meta-data android:name="android.appwidget.provider" android:resource="@xml/item_app_widget_info" /> </receiver> <!-- 小工具設定元件 --> <activity android:name=".ItemAppWidgetConfigureActivity" > <!-- 一定要加入這個設定 --> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter> </activity> 完成這一章所有的功能了,執行應用程式,使用一開始介紹的方式,加入幾個記事小工具。 課程相關的檔案都可以GitHub瀏覽與下載。 http://github.com/macdidi5/AndroidTutorial 後續 >> Android Tutorial 第六堂(1)Material Design – Theme 與 Transition |