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 為基礎的測試,請參閱 Readme 檔案 packages/apps/Settings/tests/robotests/README.md
。
外掛程式風格的資訊架構
每個設定項目都會實作為偏好設定。偏好設定可輕鬆從一個頁面移到另一個頁面。
為方便移動多項設定,Android 8.0 導入了包含設定項目的外掛程式樣式主機片段。設定項目會以外掛程式樣式的控制器建模。因此,設定頁面是由單一主機片段和多個設定控制器建構而成。
DashboardFragment
DashboardFragment
是外掛程式樣式偏好設定控制器的主機。
這個片段會從 PreferenceFragment
繼承,並提供擴展和更新靜態偏好設定清單和動態偏好設定清單的掛鉤。
靜態偏好設定
靜態偏好設定清單是使用 <Preference>
標記在 XML 中定義。DashboardFragment
實作項目會使用 getPreferenceScreenResId()
方法,定義要顯示靜態偏好設定清單的 XML 檔案。
動態偏好設定
動態項目代表具有意圖的資訊方塊,可導向外部或內部活動。意圖通常會導向其他設定頁面。舉例來說,設定首頁中的「Google」設定項目是動態項目。動態項目定義於 AndroidManifest
(詳見下文),並透過 FeatureProvider
(定義為
DashboardFeatureProvider
) 載入。
動態設定比靜態設定更耗用資源,因此開發人員通常應將設定實作為靜態設定。不過,在下列任一情況下,動態設定可能很有用:
- 設定並非直接在「設定」應用程式中實作 (例如插入由 OEM/電信業者應用程式實作的設定)。
- 設定應會顯示在「設定」首頁。
- 您已擁有設定的 Activity,且不想實作額外的靜態設定。
如要將「活動」設為動態設定,請按照下列步驟操作:
- 在活動中新增意圖篩選器,將活動標示為動態設定。
- 向「設定」應用程式說明該類別的用途。類別是
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>
在算繪時,片段會要求提供靜態 XML 和 AndroidManifest
中定義的動態設定,兩者皆為偏好設定清單。無論 PreferenceController
是在 Java 程式碼中定義,還是以 XML 定義,DashboardFragment
都會透過 PreferenceController
管理各項設定的處理邏輯 (詳見下文)。然後在使用者介面中顯示為混合清單。
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
的介面具有 isAvailable()
、
displayPreference()
、handlePreferenceTreeClicked()
等 API。如要瞭解各個 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
。如果舊網頁的 XML 中定義了PreferenceController
,請在新網頁的 XML 中也定義該項目。
Android 9 的動態移動
- 找出原始網頁和目標網頁所屬的類別。你可以在
DashboardFragmentRegistry
中找到這項資訊。 - 開啟包含要移動設定的
AndroidManifest.xml
檔案,然後找出代表這項設定的活動項目。 - 將
com.android.settings.category
的活動中繼資料值設為新網頁的類別鍵。
Android 8.x 版本中的靜態移動
- 找出原始網頁和目的地網頁的偏好設定 XML 檔案。 您可以透過頁面的
- 在原始網頁的 XML 中移除偏好設定。
- 將偏好設定新增至目的地網頁的 XML。
- 在原始頁面的 Java 實作中,移除這項偏好設定的
PreferenceController
。通常位於getPreferenceControllers()
。 - 在到達網頁的
getPreferenceControllers()
中,例項化PreferenceController
。
getPreferenceScreenResId()
方法取得這項資訊。注意:偏好設定可能沒有 PreferenceController
。
Android 8.x 版本中的動態移動
- 找出原始網頁和目標網頁所屬的類別。您可以在
DashboardFragmentRegistry
中找到這項資訊。 - 開啟包含要移動設定的
AndroidManifest.xml
檔案,然後找出代表這項設定的活動項目。 - 變更活動的
com.android.settings.category
中繼資料值,將值點設為新網頁的類別鍵。
在頁面中建立新的偏好設定
如果偏好設定靜態列於原始頁面的偏好設定 XML 檔案中,請按照下方的靜態程序操作。否則請按照動態程序操作。
建立靜態偏好設定
- 找出網頁的偏好設定 XML 檔案。您可以透過頁面的 getPreferenceScreenResId() 方法找到這項資訊。
- 在 XML 中新增 Preference 項目。確認該項目有專屬的
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 測試。所有現有和新的測試都應通過。
- 建構並安裝「設定」,然後手動開啟要修改的頁面。 頁面應該會立即更新。