Architektura informacji

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ń umożliwiających dostosowanie urządzenia 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 Ustawieniach jest obecnie zaimplementowana za pomocą nowej platformy. Dobrym przykładem są Ustawienia wyświetlacza: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

Poniżej znajdziesz ścieżki 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 (wprowadzone w Androidzie 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Implementacja

Zachęcamy producentów urządzeń do dostosowania obecnej architektury informacji o Ustawieniach i wstawienie dodatkowych stron ustawień, aby dostosować je do funkcji specyficznych dla partnerów. Przenoszenie preferencji ze starszej strony (zaimplementowanej jako SettingsPreferencePage) na nową stronę (zaimplementowanego za pomocą DashboardFragment) może być skomplikowane. Preferencja ze starszej strony prawdopodobnie nie jest zaimplementowana za pomocą elementu 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, których wymaga PreferenceController, są opisane w ich nazwie i udokumentowane w Javadoc.

Zdecydowanie zalecamy dodanie testu jednostkowego do 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 zaimplementowany jako preferencja. Preferencje można łatwo przenieść 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 przypominające wtyczki. W związku z tym strona ustawień składa się z pojedynczego fragmentu hosta i kilku kontrolerów ustawień.

Fragment panelu

DashboardFragment jest hostem kontrolerów preferencji stylu wtyczki. Fragment jest dziedziczony z elementu PreferenceFragment i zawiera elementy zaczepienia pozwalające rozwijać i aktualizować zarówno statyczne, jak i dynamiczne listy preferencji.

Ustawienia statyczne

Statyczna lista preferencji jest zdefiniowana w pliku XML za pomocą tagu <Preference>. Implementacja DashboardFragment używa metody getPreferenceScreenResId(), aby określić, który plik XML zawiera statyczną listę preferencji do wyświetlenia.

Preferencje dynamiczne

Element dynamiczny reprezentuje kafelek z intencją, który prowadzi do aktywności zewnętrznej lub wewnętrznej. Zwykle intencja prowadzi do innej strony ustawień. Na przykład element ustawienia „Google” na stronie głównej Ustawień jest elementem dynamicznym. Elementy dynamiczne są zdefiniowane w zasadzie AndroidManifest (opis znajdziesz poniżej) i wczytywane za pomocą FeatureProvider (zdefiniowanego jako DashboardFeatureProvider).

Ustawienia dynamiczne mają większe znaczenie niż ustawienia konfigurowane statycznie, więc deweloperzy zwykle powinni wdrożyć je jako statyczne. Ustawienie dynamiczne może być jednak przydatne, gdy jest spełniony 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).
  • To ustawienie powinno się pojawić na stronie głównej Ustawień.
  • Masz już aktywność dla tego ustawienia i nie chcesz implementować dodatkowej konfiguracji statycznej.

Aby skonfigurować Działanie jako ustawienie dynamiczne:

  • Oznacz aktywność jako ustawienie dynamiczne, dodając do niej filtr intencji.
  • Poinformuj aplikację Ustawienia, do której kategorii należy. Kategoria jest stałą, zdefiniowaną w funkcji CategoryKey.
  • Opcjonalnie: po wyświetleniu ustawienia dodaj tekst podsumowania.

Oto przykład w aplikacji Ustawienia na urządzeniu 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>

Podczas renderowania fragment poprosi o listę ustawień zarówno ze statycznego pliku XML, jak i ustawień dynamicznych zdefiniowanych w AndroidManifest. Niezależnie od tego, czy elementy PreferenceController są zdefiniowane w kodzie Java czy w pliku XML, DashboardFragment zarządza logiką każdego ustawienia za pomocą funkcji PreferenceController (opis znajdziesz poniżej). Następnie wyświetlają się w interfejsie w postaci mieszanej listy.

Kontroler preferencji

Istnieją różnice między implementacją PreferenceController w Androidzie 9 i Androidzie 8.x, co opisaliśmy w tej sekcji.

PreferenceController w Androidzie 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 podklasy klasy BasePreferenceController. Każda z nich jest mapowana do określonego stylu interfejsu, który domyślnie obsługuje aplikacja 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ółowa dokumentacja każdego interfejsu API znajduje się w klasie interfejsu.

Ograniczenie implementacji klasy BasePreferenceController (i jej podklas, takich jak TogglePreferenceController) polega na tym, że podpis konstruktora musi spełniać jeden z tych warunków:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

Podczas instalowania preferencji dotyczących fragmentu panel udostępnia metodę dołączania parametru PreferenceController przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, aby wszystkie przyszłe zdarzenia były do niego wysyłane.

DashboardFragment przechowuje listę elementów PreferenceController na ekranie. We fragmencie kodu onCreate() wywoływane są wszystkie kontrolery dla metody getAvailabilityStatus(), a jeśli zwraca wartość prawda, w celu przetworzenia logiki wyświetlania wywoływane są wszystkie kontrolery displayPreference(). getAvailabilityStatus()Ważne jest też poinformowanie platformy Ustawienia, 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.

Odpowiadając na interakcje z preferencjami, interfejs PreferenceController zawiera interfejsy API isAvailable(), displayPreference(), handlePreferenceTreeClicked() itd. Szczegółową dokumentację każdego interfejsu API znajdziesz w klasie interfejsu.

Podczas instalowania preferencji dotyczących fragmentu panel udostępnia metodę dołączania parametru PreferenceController przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, aby wszystkie przyszłe zdarzenia były do niego wysyłane.

DashboardFragment przechowuje na ekranie listę elementów PreferenceControllers . W elemencie onCreate() fragmentu wszystkie kontrolery są wywoływane dla metody isAvailable(), a jeśli zwraca wartość prawda, w celu przetworzenia logiki wyświetlania wywoływane są wszystkie kontrolery displayPreference().

Użyj elementu DashboardFragment

Przenoszenie preferencji ze strony A na B

Jeśli ustawienie jest statycznie wymienione w pliku XML preferencji strony oryginalnej, wykonaj podaną niżej procedurę przenoszenia statycznego dla odpowiedniej wersji Androida. W przeciwnym razie wykonaj procedurę dynamicznego przenoszenia dla Twojej wersji Androida.

Statyczne zmiany na Androidzie 9

  1. Znajdź preferowane pliki XML strony oryginalnej i strony docelowej. Te informacje możesz znaleźć za pomocą metody getPreferenceScreenResId() strony.
  2. Usuń tę preferencję z kodu XML strony oryginalnej.
  3. Dodaj tę preferencję do kodu XML strony docelowej.
  4. Usuń dla tego ustawienia element PreferenceController z implementacji Java oryginalnej strony. Zwykle znajduje się w tym regionie: createPreferenceControllers(). Kontroler może być zadeklarowany bezpośrednio w pliku XML.

    Uwaga: to ustawienie może nie mieć wartości PreferenceController.

  5. Utwórz instancję PreferenceController w tagu createPreferenceControllers() strony docelowej. Jeśli atrybut PreferenceController jest zdefiniowany w pliku XML na starej stronie, określ go w pliku XML również dla nowej strony.

Dynamiczne przenoszenie na Androidzie 9

  1. Sprawdź, która kategoria zawiera strona oryginalna i strona docelowa. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Otwórz plik AndroidManifest.xml zawierający ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie.
  3. Ustaw wartość metadanych aktywności w przypadku com.android.settings.category na klucz kategorii nowej strony.

Statyczne zmiany w wersjach Androida 8.x

  1. Znajdź preferowane pliki XML strony oryginalnej i strony docelowej.
  2. Te informacje możesz znaleźć za pomocą metody getPreferenceScreenResId() strony.
  3. Usuń to ustawienie w kodzie XML strony oryginalnej.
  4. Dodaj preferencję do pliku XML strony docelowej.
  5. Usuń w jej przypadku parametr PreferenceController w implementacji Java strony oryginalnej. Zazwyczaj jest w tym regionie: getPreferenceControllers().
  6. Uwaga: możliwe, że ustawienie nie ma parametru PreferenceController.

  7. Utwórz instancję PreferenceController w tagu getPreferenceControllers() strony docelowej.

Dynamiczne przenoszenie w wersjach Androida 8.x

  1. Sprawdź, która kategoria zawiera strona oryginalna i strona docelowa. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Otwórz plik AndroidManifest.xml zawierający ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie.
  3. Zmień wartość metadanych aktywności w polu com.android.settings.category, ustaw wartość jako klucz kategorii nowej strony.

Utwórz nowe ustawienie na stronie

Jeśli ustawienie jest statycznie wymienione w pliku XML preferencji strony oryginalnej, postępuj zgodnie z podaną niżej procedurą statycznej. W przeciwnym razie wykonaj procedurę dynamiczną.

Utwórz ustawienie statyczne

  1. Znajdź preferowane pliki XML dla strony. Te informacje możesz znaleźć za pomocą metody getPreferenceScreenResId() na stronie.
  2. Dodaj nowy element preferencji w pliku XML. Upewnij się, że jest w niej unikalny android:key.
  3. Określ PreferenceController dla tej preferencji w metodzie getPreferenceControllers() strony.
    • W Androidzie 8.x i opcjonalnie w Androidzie 9 utwórz dla tej preferencji właściwość PreferenceController w metodzie createPreferenceControllers() strony.

      Jeśli to ustawienie występuje już w innych miejscach, możliwe, że ma już ustawienie PreferenceController. Możesz użyć zasobu PreferenceController bez tworzenia nowego.

    • Począwszy od Androida 9 można zadeklarować PreferenceController w pliku XML obok preferencji. Przykład:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

Tworzenie preferencji dynamicznych

  1. Sprawdź, która kategoria zawiera strona oryginalna i strona docelowa. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Utwórz nową aktywność na zajęciach AndroidManifest
  3. Dodaj do nowego działania niezbędne metadane, aby zdefiniować ustawienie. Ustaw wartość metadanych obiektu com.android.settings.category na taką samą wartość, jaka została określona w kroku 1.

Utwórz nową stronę

  1. Utwórz nowy fragment o dziedziczeniu z elementu DashboardFragment.
  2. Określ jego kategorię w: DashboardFragmentRegistry.

    Uwaga: ten krok jest opcjonalny. Jeśli na tej stronie nie potrzebujesz żadnych dynamicznych ustawień, nie musisz podawać klucza kategorii.

  3. Postępuj zgodnie z instrukcjami dodawania ustawień wymaganych dla tej strony. Więcej informacji znajdziesz w sekcji Implementacja.

Weryfikacja

  • Uruchom testy automatyczne w Ustawieniach. Wszystkie istniejące i nowe testy powinny zakończyć się powodzeniem.
  • Skompiluj i zainstaluj Ustawienia, a następnie ręcznie otwórz modyfikowaną stronę. Strona powinna się natychmiast zaktualizować.