W Androidzie 8.0 wprowadziliśmy w aplikacji Ustawienia nową architekturę informacji, która upraszcza porządkowanie ustawień i ułatwia użytkownikom szybkie znajdowanie ustawień, które pozwalają na dostosowanie urządzeń z Androidem. W Androidzie 9 wprowadziliśmy kilka ulepszeń, które zwiększają funkcjonalność ustawień i ułatwiają implementację.
Przykłady i źródło
Większość stron w sekcji Ustawienia jest obecnie implementowana za pomocą nowego frameworku. Dobrym przykładem jest DisplaySettings:packages/apps/Settings/src/com/android/settings/DisplaySettings.java
Ścieżki do plików ważnych komponentów:
- CategoryKey (Klucz kategorii):
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 (wprowadzony w Androidzie 9):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
Implementacja
Producentów urządzeń zachęcamy do dostosowania istniejącej architektury informacji w ustawieniach i do dodania dodatkowych stron ustawień w celu uwzględnienia funkcji partnerów. Przenoszenie ustawień ze starszej strony (implementowanej za pomocą funkcji SettingsPreferencePage
) na nową stronę (implementowaną za pomocą funkcji DashboardFragment
) może być skomplikowane. Ustawienie ze starszej strony jest prawdopodobnie niewdrożone za pomocą funkcji PreferenceController
.
Jeśli więc przenosisz preferencje ze starszej strony na nową, musisz utworzyć PreferenceController
i przenieść kod do kontrolera, zanim zainicjujesz go w nowym elemencie DashboardFragment
. Interfejsy API wymagane przez PreferenceController
są opisane w swoich nazwach i opisane w dokumentacji Javadoc.
Zdecydowanie zalecamy dodanie testu jednostkowego dla każdego elementu PreferenceController
.
Jeśli zmiana zostanie przesłana do AOSP, wymagany jest test jednostkowy.
Więcej informacji o pisaniu testów opartych na Robolectric znajdziesz w pliku readme packages/apps/Settings/tests/robotests/README.md
.
Architektura informacji w stylu wtyczki
Każdy element ustawień jest implementowany jako ustawienie. Ustawienia można łatwo przenosić z jednej strony na inną.
Aby ułatwić przenoszenie wielu ustawień, w Androidzie 8.0 wprowadzono fragment hosta w stylu wtyczki, który zawiera elementy ustawień. Elementy ustawień są modelowane jako kontrolery w stylu wtyczki. Strona ustawień jest więc tworzona przez pojedynczy fragment hosta i wiele kontrolerów ustawień.
DashboardFragment
DashboardFragment
jest hostem sterowników ustawień w stylu wtyczki.
Fragment dziedziczy z PreferenceFragment
i zawiera elementy wywołujące, które służą do rozszerzania i aktualizowania zarówno statycznych, jak i dynamicznych list preferencji.
Ustawienia statyczne
Statyczna lista preferencji jest zdefiniowana w pliku XML za pomocą tagu <Preference>
. Wdrożenie DashboardFragment
używa metody getPreferenceScreenResId()
, aby określić, który plik XML zawiera stałą listę preferencji do wyświetlenia.
Preferencje dynamiczne
Element dynamiczny reprezentuje kartę z zawartą w niej intencją, która prowadzi do działania zewnętrznego lub wewnętrznego. Zwykle prowadzi ona do innej strony ustawień. Na przykład element ustawienia „Google” na stronie głównej Ustawień jest elementem dynamicznym. Elementy dynamiczne są definiowane w definicji AndroidManifest
(omówionej poniżej) i ładowane za pomocą FeatureProvider
(zdefiniowanego jako
DashboardFeatureProvider
).
Ustawienia dynamiczne są bardziej obciążające niż skonfigurowane statycznie, dlatego programiści powinni stosować je jako statyczne. Ustawienie dynamiczne może być jednak przydatne, gdy spełniony jest dowolny z tych warunków:
- To ustawienie nie jest bezpośrednio wdrażane w aplikacji Ustawienia (np. wprowadzenie ustawienia wdrożonym przez aplikacje OEM lub operatora).
- Ustawienie powinno pojawić się na stronie głównej Ustawień.
- Masz już aktywność dla tego ustawienia i nie chcesz implementować dodatkowej konfiguracji statycznej.
Aby skonfigurować aktywność jako ustawienie dynamiczne:
- Oznacz aktywność jako ustawienie dynamiczne, dodając do działania filtr intencji.
- Powiedz aplikacji Ustawienia, do której kategorii należy. Kategoria jest stałą wartością zdefiniowaną w pliku
CategoryKey
. - Opcjonalnie: po wyświetleniu ustawienia dodaj tekst podsumowania.
Oto przykład z aplikacji Ustawienia dla 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>
W momencie renderowania fragment poprosi o listę preferencji z zarówno statycznych elementów XML, jak i ustawień dynamicznych zdefiniowanych w pliku AndroidManifest
. Niezależnie od tego, czy PreferenceController
są zdefiniowane w kodzie Java czy w pliku XML, DashboardFragment
zarządza logiką obsługi każdego ustawienia za pomocą PreferenceController
(omówionego poniżej). Następnie są wyświetlane w interfejsie jako lista mieszana.
PreferenceController
W tym rozdziale opisujemy różnice między implementacją PreferenceController
w Androidzie 9 a Androidem 8.x.
PreferenceController w wersji Androida 9
PreferenceController
zawiera wszystkie funkcje logiczne umożliwiające interakcję z preferencjami, w tym wyświetlanie, aktualizowanie, indeksowanie wyszukiwania itp.
Interfejs PreferenceController
jest zdefiniowany jako BasePreferenceController
. Zobacz np. kod tutaj: packages/apps/Settings/src/com/android/settings/core/
BasePreferenceController.java
Istnieje kilka podklas BasePreferenceController
, z których każda odpowiada określonemu stylowi interfejsu obsługiwanemu domyślnie przez aplikację Ustawienia. Na przykład TogglePreferenceController
ma interfejs API, który bezpośrednio mapuje sposób interakcji użytkownika z interfejsem użytkownika opartym na przełącznikach.
BasePreferenceController
ma interfejsy API takie jak getAvailabilityStatus()
, displayPreference()
, handlePreferenceTreeClicked(),
itp. Szczegółowe informacje o każdym interfejsie API znajdziesz w klasie interfejsu.
Ograniczeniem implementacji klasy BasePreferenceController
(i jej podklas, takich jak TogglePreferenceController
) jest to, że podpis konstruktora musi spełniać jeden z tych warunków:
public MyController(Context context, String key) {}
public MyController(Context context) {}
Podczas instalowania preferencji do fragmentu panel oferuje metodę dołączania PreferenceController
przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe zdarzenia są wysyłane do kontrolera.
DashboardFragment
przechowuje na ekranie listę PreferenceController
. W miejscu fragmentu onCreate()
wywoływane są wszystkie kontrolery dla metody getAvailabilityStatus()
, a jeśli zwróci ona wartość true, wywoływana jest metoda displayPreference()
, aby przetworzyć logikę wyświetlania.
getAvailabilityStatus()
jest też ważne, aby poinformować framework ustawień, które elementy są dostępne podczas wyszukiwania.
PreferenceController w Androidzie 8.x
PreferenceController
zawiera wszystkie funkcje logiczne umożliwiające interakcję z preferencjami, w tym wyświetlanie, aktualizowanie, indeksowanie wyszukiwania itp.
W zależności od interakcji z preferencjami interfejs
PreferenceController
zawiera interfejsy API isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
itp. Szczegółową dokumentację każdego interfejsu API znajdziesz w klasie interfejsu.
Podczas instalowania preferencji do fragmentu panel oferuje metodę dołączania PreferenceController
przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe zdarzenia są wysyłane do kontrolera.
DashboardFragment
przechowuje na ekranie listę elementów PreferenceControllers
. W miejscu onCreate()
fragmentu wywoływane są wszystkie kontrolery dla metody isAvailable()
, a jeśli zwróci ona wartość true, wywoływana jest metoda displayPreference()
, aby przetworzyć logikę wyświetlania.
Użyj elementu DashboardFragment
Przenoszenie ustawienia ze strony A na stronę B
Jeśli ustawienie jest wymienione statycznie w pliku XML preferencji oryginalnej strony, wykonaj poniżej procedurę przenoszenia statycznego dla wersji Androida. W przeciwnym razie postępuj zgodnie z procedurą przenoszenia Dynamic w przypadku wersji na Androida.
Przenoszenie statyczne w Androidzie 9
- Znajdź pliki XML ustawień oryginalnej strony i strony docelowej. Te informacje znajdziesz w metodie
getPreferenceScreenResId()
strony. - Usuń ustawienie z pliku XML oryginalnej strony.
- Dodaj ustawienie do pliku XML strony docelowej.
- Usuń z implementacji Javy oryginalnej strony element
PreferenceController
odpowiadający tej opcji. Zazwyczaj jest tocreatePreferenceControllers()
. Kontroler może być zadeklarowany bezpośrednio w pliku XML.Uwaga: ustawienie może nie mieć wartości
PreferenceController
. - Utwórz instancję klasy
PreferenceController
w komponenciecreatePreferenceControllers()
na stronie docelowej. Jeśli elementPreferenceController
jest zdefiniowany w pliku XML starej strony, zdefiniuj go też w pliku XML nowej strony.
Dynamiczne przenoszenie w Androidzie 9
- Sprawdź, do której kategorii należy strona docelowa i oryginalna. Te informacje znajdziesz na stronie
DashboardFragmentRegistry
. - Otwórz plik
AndroidManifest.xml
zawierający ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie. - Ustaw wartość metadanych aktywności w przypadku
com.android.settings.category
na klucz kategorii nowej strony.
Statyczne przenoszenie w wersjach Androida 8.x
- Znajdź pliki XML ustawień oryginalnej strony i strony docelowej. Te informacje możesz znaleźć za pomocą metody
- Usuń to ustawienie w kodzie XML strony oryginalnej.
- Dodaj ustawienie do pliku XML strony docelowej.
- Usuń w jej przypadku parametr
PreferenceController
w implementacji Java swojej pierwotnej strony. Zwykle jest togetPreferenceControllers()
. - Utwórz instancję klasy
PreferenceController
w komponenciegetPreferenceControllers()
strony docelowej.
getPreferenceScreenResId()
strony.
Uwaga: może się zdarzyć, że ustawienie nie ma parametru PreferenceController
.
Dynamiczny ruch w wersjach Androida 8.x
- Sprawdź, która kategoria zawiera strona oryginalna i strona docelowa. Te informacje znajdziesz na stronie
DashboardFragmentRegistry
. - Otwórz plik
AndroidManifest.xml
zawierający ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie. - Zmień wartość metadanych aktywności dla elementu
com.android.settings.category
, ustaw wartość jako klucz kategorii nowej strony.
Utwórz nowe ustawienie na stronie
Jeśli ustawienie jest wymienione statycznie w pliku XML z ustawieniami oryginalnej strony, wykonaj podaną niżej procedurę statyczną. W przeciwnym razie wykonaj procedurę dynamiczną.
Tworzenie preferencji statycznej
- Znajdź pliki XML ustawień strony. Te informacje można znaleźć w metodzie getPreferenceScreenResId() strony.
- Dodaj nowy element preferencji w pliku XML. Upewnij się, że jest w niej unikalny
android:key
. -
Określ
PreferenceController
dla tego ustawienia w metodziegetPreferenceControllers()
strony.- W Androidzie 8.x i opcjonalnie w Androidzie 9 utwórz dla tej preferencji właściwość
PreferenceController
w metodziecreatePreferenceControllers()
strony.Jeśli to ustawienie występuje już w innych miejscach, możliwe, że ma już ustawienie
PreferenceController
. Możesz użyć zasobuPreferenceController
bez tworzenia nowego. -
Począwszy od Androida 9 można zadeklarować
PreferenceController
w pliku XML obok preferencji. Na przykład:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- W Androidzie 8.x i opcjonalnie w Androidzie 9 utwórz dla tej preferencji właściwość
Tworzenie preferencji dynamicznych
- Sprawdź, do której kategorii należy strona docelowa i oryginalna. Te informacje znajdziesz na stronie
DashboardFragmentRegistry
. - Utwórz nową aktywność na zajęciach
AndroidManifest
- Dodaj do nowego działania niezbędne metadane, aby zdefiniować ustawienie. Ustaw wartość metadanych
com.android.settings.category
na tę samą wartość, która została zdefiniowana w kroku 1.
Utwórz nową stronę
- Utwórz nowy fragment, dziedziczący z poziomu
DashboardFragment
. - Zdefiniuj kategorię w parametrye
DashboardFragmentRegistry
.Uwaga: ten krok jest opcjonalny. Jeśli nie potrzebujesz żadnych ustawień dynamicznych na tej stronie, nie musisz podawać klucza kategorii.
- Postępuj zgodnie z instrukcjami dodawania ustawień wymaganych dla tej strony. Więcej informacji znajdziesz w sekcji Implementacja.
Weryfikacja
- Uruchom testy robolectric w Ustawieniach. Wszystkie istniejące i nowe testy powinny przejść.
- Utwórz i zainstaluj Ustawienia, a potem ręcznie otwórz stronę, którą chcesz zmodyfikować. Strona powinna się natychmiast zaktualizować.