Android 8.0 為「設定」應用程式推出了新的資訊架構,以簡化各項設定的整理方式,讓使用者能更輕鬆快速地找到自訂 Android 裝置的設定。Android 9 推出了幾項改善功能,提供更多設定功能,並簡化實作程序。
範例和來源
「設定」中大部分的網頁目前都使用新架構來導入。DisplaySettings 就是一個很好的例子:packages/apps/Settings/src/com/android/settings/DisplaySettings.java
以下列出重要元件的檔案路徑:
- CategoryKey:
packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
- DashboardFragmentRegistry:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
- DashboardFragment:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
- AbstractPreferenceController:
frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
- BasePreferenceController (於 Android 9 推出):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
導入作業
我們建議裝置製造商調整現有的「設定」資訊架構,並視需求插入其他設定頁面,以滿足合作夥伴專屬功能。將偏好設定從舊版頁面 (以 SettingsPreferencePage
實作) 移至新頁面 (使用 DashboardFragment
實作) 可能並不容易。PreferenceController
可能無法導入舊版頁面的偏好設定。
因此,將偏好設定從舊版頁面移至新頁面時,您需要建立 PreferenceController
並將程式碼移至控制器,再於新的 DashboardFragment
中執行個體化偏好設定。PreferenceController
需要的 API 於其名稱中說明,並記錄在 Javadoc 中。
強烈建議您為每個 PreferenceController
新增單元測試。如果變更內容提交至 Android 開放原始碼計畫,就必須進行單元測試。如要進一步瞭解如何編寫以 Robolectric 為基礎的測試,請參閱讀取檔案 packages/apps/Settings/tests/robotests/README.md
。
外掛程式樣式資訊架構
每個設定項目都會做為偏好設定。您可以在不同頁面之間輕鬆調整偏好設定。
為方便您移動多項設定,Android 8.0 推出了一個包含設定項目的外掛程式樣式主機片段。系統會將設定項目建模為外掛程式樣式控制器。因此,設定頁面是由單一主機片段和多個設定控制器所建構。
資訊主頁片段
DashboardFragment
是外掛程式樣式的偏好設定控制器主機。片段繼承自 PreferenceFragment
,並且具有掛鉤展開及更新靜態偏好設定清單和動態偏好設定清單。
靜態偏好設定
靜態偏好設定清單是在 XML 中使用 <Preference>
標記定義。DashboardFragment
實作會使用 getPreferenceScreenResId()
方法,定義哪個 XML 檔案包含要顯示的靜態偏好設定清單。
動態偏好設定
動態項目代表一個資訊方塊,該資訊方塊會導向外部或內部活動。一般來說,該意圖會將使用者導向不同的設定頁面。例如,「設定」首頁中的「Google」設定項目是動態項目。動態項目會在 AndroidManifest
中定義 (如下所述),並透過 FeatureProvider
(定義為
DashboardFeatureProvider
) 載入。
動態設定比靜態設定的設定更複雜,因此一般開發人員應將此設定實作為靜態設定。不過,動態設定在下列任一情況下都很實用:
- 系統不會直接在「設定」應用程式中實作這項設定 (例如插入 OEM/電信業者應用程式實作的設定)。
- 「設定」首頁應會顯示這項設定。
- 設定中已有「活動」設定,且不想實作額外靜態設定。
如要將活動設為動態設定,請按照下列步驟操作:
- 只要在活動中新增意圖篩選器,即可將活動標示為動態設定。
- 告知「設定」應用程式所屬的類別。類別是在
CategoryKey
中定義的常數。 - 選用:在顯示設定時新增摘要文字。
以下是從「設定」應用程式 DisplaySettings
取得的範例。
<activity android:name="Settings$DisplaySettingsActivity" android:label="@string/display_settings" android:icon="@drawable/ic_settings_display"> <!-- Mark the activity as a dynamic setting --> <intent-filter> <action android:name="com.android.settings.action.IA_SETTINGS" /> </intent-filter> <!-- Tell Settings app which category it belongs to --> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.homepage" /> <!-- Add a summary text when the setting is displayed --> <meta-data android:name="com.android.settings.summary" android:resource="@string/display_dashboard_summary"/> </activity>
在轉譯時,片段會要求提供清單,同時來自 AndroidManifest
中定義的靜態 XML 和動態設定。無論 PreferenceController
是在 Java 程式碼中或 XML 中定義,DashboardFragment
都會透過 PreferenceController
管理每項設定的處理邏輯 (如下所述)。然後在 UI 中以混合清單的形式顯示。
PreferenceController
在 Android 9 和 Android 8.x 中實作 PreferenceController
有所不同,如本節所述。
Android 9 中的 PreferenceController
PreferenceController
包含與偏好設定互動的所有邏輯,包括顯示、更新、搜尋索引等。
PreferenceController
介面定義為 BasePreferenceController
。例如,請參閱 packages/apps/Settings/src/com/android/settings/core/
BasePreferenceController.java
中的程式碼
BasePreferenceController
有多個子類別,每個子類別都會對應至「設定」應用程式預設支援的特定 UI 樣式。舉例來說,TogglePreferenceController
的 API 會直接對應至使用者應如何與切換型偏好設定 UI 互動。
BasePreferenceController
具有 getAvailabilityStatus()
、displayPreference()
、handlePreferenceTreeClicked(),
等 API。各 API 的詳細說明文件位於介面類別。
如果實作 BasePreferenceController
(及其子類別,例如 TogglePreferenceController
) 的限制,建構函式簽章必須符合下列任一條件:
public MyController(Context context, String key) {}
public MyController(Context context) {}
為片段安裝偏好設定時,資訊主頁會提供方法,讓您在顯示時間前附加 PreferenceController
。在安裝時,控制器會連結片段,因此所有日後的相關事件都會傳送至控制器。
DashboardFragment
會在畫面中保留 PreferenceController
清單。在片段的 onCreate()
中,系統會針對 getAvailabilityStatus()
方法叫用所有控制器;如果傳回 true,就會叫用 displayPreference()
來處理顯示邏輯。getAvailabilityStatus()
也重要的是告知設定架構,哪些項目可在搜尋時派上用場。
Android 8.x 版本中的 PreferenceController
PreferenceController
包含與偏好設定互動的所有邏輯,包括顯示、更新、搜尋索引等。
對應至偏好設定互動,
PreferenceController
的介麵包含 API isAvailable()
、
displayPreference()
、handlePreferenceTreeClicked()
等。您可以在介面類別中找到各個 API 的詳細說明文件。
為片段安裝偏好設定時,資訊主頁會提供方法,讓您在顯示時間前附加 PreferenceController
。在安裝時,控制器會連接至片段,因此日後所有相關事件都會傳送至控制器。
DashboardFragment
會在畫面中保留 PreferenceControllers
清單。在片段的 onCreate()
中,系統會針對 isAvailable()
方法叫用所有控制器;如果傳回 true,則會叫用 displayPreference()
來處理顯示邏輯。
使用 DashboardFragment
將偏好設定從網頁 A 移至 B
如果偏好設定是靜態列在原始頁面偏好設定 XML 檔案中,請根據您 Android 版本適用的「靜態」移動程序操作。否則,請按照 Android 版本適用的動態移動程序操作。
Android 9 中的靜態動作
- 找出原始網頁和到達網頁的偏好設定 XML 檔案。您可以從頁面的
getPreferenceScreenResId()
方法找到這項資訊。 - 移除原始網頁的 XML 偏好設定。
- 將偏好設定新增至到達網頁的 XML。
- 從原始頁面的 Java 實作中移除此偏好設定的
PreferenceController
。通常位於createPreferenceControllers()
。系統可能會直接在 XML 中宣告這個控制器。注意:偏好設定沒有
PreferenceController
。 - 在到達網頁的
createPreferenceControllers()
中將PreferenceController
例項化。如果PreferenceController
是在舊頁面的 XML 中定義,請一併在新頁面的 XML 中定義該值。
Android 9 中的動態移動
- 找出原始網頁和到達網頁代管的類別。您可以在
DashboardFragmentRegistry
中找到這項資訊。 - 開啟包含要移動設定的
AndroidManifest.xml
檔案,找出代表這項設定的 Activity 項目。 - 將
com.android.settings.category
的活動中繼資料值設為新頁面的類別鍵。
Android 8.x 版本中的靜態移動
- 找出原始網頁和到達網頁的偏好設定 XML 檔案。 您可以在頁面的
- 移除原始網頁 XML 中的偏好設定。
- 將偏好設定新增至到達網頁的 XML。
- 在原始頁面的 Java 實作中,移除這項偏好設定的
PreferenceController
。通常位於getPreferenceControllers()
。 - 在到達網頁的
getPreferenceControllers()
中將PreferenceController
例項化。
getPreferenceScreenResId()
方法中找到這項資訊。注意:偏好設定可能沒有 PreferenceController
。
Android 8.x 版的動態移動
- 找出原始網頁和到達網頁代管的類別。您可以在
DashboardFragmentRegistry
中找到這項資訊。 - 開啟包含要移動設定的
AndroidManifest.xml
檔案,找出代表這項設定的 Activity 項目。 - 變更
com.android.settings.category
的活動中繼資料值,將值點設為新頁面的類別鍵。
在頁面中建立新的偏好設定
如果偏好設定是靜態列在原始網頁的偏好設定 XML 檔案中,請遵循下方的靜態程序。如果沒有,請按照動態程序進行。
建立靜態偏好設定
- 找出該網頁的偏好設定 XML 檔案。這項資訊可從頁面的 getPreferenceScreenResId() 方法中找到。
- 在 XML 中新增偏好設定項目。請確認變數均不重複
android:key
。 -
在頁面的
getPreferenceControllers()
方法中,為這項偏好設定定義PreferenceController
。- 在 Android 8.x 和 Android 9 中,請在頁面的
createPreferenceControllers()
方法中,為此偏好設定執行個體化PreferenceController
。如果這項偏好設定已存在於其他位置,則可能已有
PreferenceController
。您可以重複使用PreferenceController
,不必建構新的項目。 -
從 Android 9 開始,您可以在偏好設定旁,選擇在 XML 中宣告
PreferenceController
。例如:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- 在 Android 8.x 和 Android 9 中,請在頁面的
建立動態偏好設定
- 找出原始網頁和到達網頁代管的類別。您可以在
DashboardFragmentRegistry
中找到這項資訊。 - 在「
AndroidManifest
」中建立新活動 - 請在新的活動中新增必要的中繼資料,以便定義設定。將
com.android.settings.category
的中繼資料值設為步驟 1 中定義的值。
建立新專頁
- 建立沿用自
DashboardFragment
的新片段。 - 在
DashboardFragmentRegistry
中定義類別。注意事項:此為選用步驟。如果此頁面不需要任何動態偏好設定,則不需要提供類別鍵。
- 按照步驟新增這個頁面所需的設定。詳情請參閱「實作」一節。
驗證
- 在「設定」中執行 Robolectric 測試。所有現有和新的測試都應通過。
- 建立及安裝設定,然後手動開啟修改的頁面。 網頁會立即更新。