Информационная архитектура

В 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 . API-интерфейсы, необходимые PreferenceController , описаны в их названиях и документированы в Javadoc.

Настоятельно рекомендуется добавить модульный тест для каждого PreferenceController . Если изменение отправлено в AOSP, требуется модульный тест. Чтобы получить дополнительную информацию о том, как писать тесты на основе Robolectric, см. файл readme 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>

Во время рендеринга фрагмент запросит список настроек как из статического XML, так и из динамических настроек, определенных в AndroidManifest . Независимо от того, определены ли PreferenceController в коде Java или в XML, DashboardFragment управляет логикой обработки каждого параметра через PreferenceController (обсуждается ниже). Затем они отображаются в пользовательском интерфейсе в виде смешанного списка.

Контроллер предпочтений

Существуют различия между реализацией PreferenceController в Android 9 и Android 8.x, как описано в этом разделе.

PreferenceController в версии Android 9

PreferenceController содержит всю логику для взаимодействия с предпочтениями, включая отображение, обновление, индексацию поиска и т. д.

Интерфейс PreferenceController определен как BasePreferenceController . Например, см. код в packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

Существует несколько подклассов BasePreferenceController , каждый из которых соответствует определенному стилю пользовательского интерфейса, который приложение «Настройки» поддерживает по умолчанию. Например, TogglePreferenceController имеет API, который напрямую определяет, как пользователь должен взаимодействовать с пользовательским интерфейсом предпочтений на основе переключателей.

BasePreferenceController имеет такие API, как getAvailabilityStatus() , displayPreference() , handlePreferenceTreeClicked(), и т. д. Подробная документация для каждого API находится в классе интерфейса.

Ограничением на реализацию BasePreferenceController (и его подклассов, таких как TogglePreferenceController ) является то, что сигнатура конструктора должна соответствовать любому из следующих значений:

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

При установке предпочтения для фрагмента панель мониторинга предоставляет метод присоединения PreferenceController перед временем отображения. Во время установки контроллер подключается к фрагменту, поэтому все будущие соответствующие события отправляются на контроллер.

DashboardFragment хранит список PreferenceController на экране. В onCreate() фрагмента все контроллеры вызываются для метода getAvailabilityStatus() , и если он возвращает true, вызывается displayPreference() для обработки логики отображения. getAvailabilityStatus() также важен для того, чтобы сообщить системе настроек, какие элементы доступны во время поиска.

PreferenceController в выпусках Android 8.x

PreferenceController содержит всю логику для взаимодействия с предпочтениями, включая отображение, обновление и индексацию поиска. и т. д.

В соответствии с взаимодействиями предпочтений интерфейс PreferenceController имеет API isAvailable() , displayPreference() , handlePreferenceTreeClicked() и т. д. Подробную документацию по каждому API можно найти в классе интерфейса.

При установке предпочтения для фрагмента панель мониторинга предоставляет метод присоединения PreferenceController перед временем отображения. Во время установки контроллер подключается к фрагменту, поэтому все будущие соответствующие события отправляются на контроллер.

DashboardFragment хранит список PreferenceControllers на экране. В onCreate() фрагмента все контроллеры вызываются для метода isAvailable() , и если он возвращает true, вызывается displayPreference() для обработки логики отображения.

Использование DashboardFragment

Перемещение предпочтения со страницы А на Б

Если настройка статически указана в XML-файле настроек исходной страницы, следуйте процедуре статического перемещения для вашей версии Android, приведенной ниже. В противном случае следуйте процедуре динамического перемещения для вашей версии Android.

Статический ход в Android 9

  1. Найдите XML-файлы предпочтений для исходной страницы и целевой страницы. Эту информацию можно найти с помощью метода getPreferenceScreenResId() страницы.
  2. Удалите настройку из XML исходной страницы.
  3. Добавьте настройку в XML целевой страницы.
  4. Удалите PreferenceController для этого предпочтения из реализации Java исходной страницы. Обычно это находится в createPreferenceControllers() . Контроллер может быть объявлен непосредственно в XML.

    Примечание . Предпочтение может не иметь PreferenceController .

  5. Создайте экземпляр PreferenceController в createPreferenceControllers() целевой страницы. Если PreferenceController определен в XML на старой странице, определите его также в XML для новой страницы.

Динамический ход в Android 9

  1. Найдите категорию, в которой размещена исходная и целевая страницы. Эту информацию можно найти в DashboardFragmentRegistry .
  2. Откройте файл AndroidManifest.xml , содержащий параметр, который необходимо переместить, и найдите запись Activity, представляющую этот параметр.
  3. Установите значение метаданных действия для com.android.settings.category в ключ категории новой страницы.

Статический ход в выпусках Android 8.x

  1. Найдите XML-файлы предпочтений для исходной страницы и целевой страницы.
  2. Эту информацию можно найти с помощью метода getPreferenceScreenResId() страницы.
  3. Удалите настройку в XML исходной страницы.
  4. Добавьте предпочтение к XML целевой страницы.
  5. Удалите PreferenceController для этого предпочтения в реализации Java исходной страницы. Обычно это getPreferenceControllers() .
  6. Примечание . Возможно, у предпочтения нет PreferenceController .

  7. Создайте экземпляр PreferenceController в getPreferenceControllers() целевой страницы.

Динамический переход в выпусках Android 8.x

  1. Найдите категорию, в которой размещена исходная и целевая страницы. Эту информацию можно найти в DashboardFragmentRegistry .
  2. Откройте файл AndroidManifest.xml , содержащий параметр, который необходимо переместить, и найдите запись Activity, представляющую этот параметр.
  3. Измените значение метаданных действия для com.android.settings.category и установите точку значения для ключа категории новой страницы.

Создание новой настройки на странице

Если предпочтение статически указано в XML-файле предпочтений исходной страницы, следуйте приведенной ниже статической процедуре. В противном случае следуйте динамической процедуре.

Создание статического предпочтения

  1. Найдите XML-файлы предпочтений для страницы. Эту информацию можно найти с помощью метода getPreferenceScreenResId() страницы.
  2. Добавьте новый элемент предпочтений в XML. Убедитесь, что у него уникальный android:key .
  3. Определите PreferenceController для этого предпочтения в методе страницы getPreferenceControllers() .
    • В Android 8.x и (необязательно) в Android 9 создайте экземпляр PreferenceController для этого предпочтения в методе createPreferenceControllers() страницы.

      Если это предпочтение уже существовало в других местах, возможно, для него уже существует PreferenceController . Вы можете повторно использовать PreferenceController без создания нового.

    • Начиная с Android 9, вы можете объявить PreferenceController в XML рядом с предпочтением. Например:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

Создание динамического предпочтения

  1. Найдите категорию, в которой размещена исходная и целевая страницы. Эту информацию можно найти в DashboardFragmentRegistry .
  2. Создайте новую активность в AndroidManifest
  3. Добавьте необходимые метаданные в новое действие, чтобы определить настройку. Установите значение метаданных для com.android.settings.category на то же значение, определенное на шаге 1.

Создать новую страницу

  1. Создайте новый фрагмент, унаследованный от DashboardFragment .
  2. Определите его категорию в DashboardFragmentRegistry .

    Примечание. Этот шаг не является обязательным. Если вам не нужны какие-либо динамические настройки на этой странице, вам не нужно указывать ключ категории.

  3. Следуйте инструкциям по добавлению настроек, необходимых для этой страницы. Более подробную информацию смотрите в разделе Реализация .

Проверка

  • Запустите робоэлектрические тесты в настройках. Все существующие и новые тесты должны пройти.
  • Создайте и установите настройки, а затем вручную откройте изменяемую страницу. Страница должна обновиться немедленно.