Перенесите свой пользовательский интерфейс на адаптивные макеты

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

Адаптивный пользовательский интерфейс основан на принципах гибкости и непрерывности.

Гибкость означает, что планировка оптимально использует доступное пространство и адаптируется при его изменении. Корректировки могут принимать разные формы: простое увеличение размера одного представления, изменение положения представлений так, чтобы они находились в более доступных местах, отображение или скрытие дополнительных представлений или сочетание этих действий.

Непрерывность означает обеспечение беспрепятственного взаимодействия с пользователем при переходе от одного размера окна к другому. Каким бы опытом ни занимался пользователь, он должен продолжаться без перерывов. Поскольку изменение размера может сопровождаться разрушением и воссозданием всей иерархии представлений, важно, чтобы пользователь не потерял свое место или свои данные.

Чего следует избегать

Избегайте использования физических, аппаратных значений для принятия решений по компоновке . Может возникнуть соблазн принимать решения на основе фиксированного значения, но во многих ситуациях эти значения бесполезны для определения пространства, с которым может работать ваш пользовательский интерфейс.

Приложения могут изменять размер окна при работе в многооконном режиме, в режиме «картинка в картинке» или в окнах произвольной формы, например ChromeOS. Физических экранов может быть даже несколько, например, в случае складного устройства или устройства с несколькими дисплеями. Во всех этих случаях физический размер экрана не имеет значения для принятия решения о том, как отображать контент.

Несколько устройств с окнами приложений разного размера.
Рисунок 1. Размеры окон могут отличаться от размера физического устройства или дисплея.

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

Также не пытайтесь определить, является ли это устройство телефоном или планшетом . То, что именно считается планшетом, является несколько субъективным: основано ли оно на наличии определенного размера, соотношения сторон или комбинации размера и соотношения сторон? По мере появления новых форм-факторов эти предположения могут измениться, и различие потеряет значение.

Вместо того, чтобы пробовать любую из предыдущих стратегий, используйте точки останова и классы размеров окон.

Точки останова и классы размеров окон

Фактическая часть экрана, выделенная для вашего приложения, является окном приложения. Оно может занимать весь экран или часть экрана, поэтому используйте размер окна при принятии высокоуровневых решений о макете вашего приложения.

При проектировании для нескольких форм-факторов найдите пороговые значения, при которых эти решения высокого уровня разветвляются в разных направлениях. С этой целью сетка адаптивного макета Material Design предоставляет контрольные точки для ширины и высоты, что позволяет сопоставлять необработанные размеры с дискретными стандартизированными группами, называемыми классами размеров окон. Из-за повсеместного распространения вертикальной прокрутки большинство приложений в первую очередь заботятся о классах размеров ширины, поэтому большинство приложений можно оптимизировать для всех размеров экрана, обрабатывая всего несколько точек останова. (Дополнительную информацию о классах размеров окон см. в разделе Классы размеров окон .)

Постоянные элементы пользовательского интерфейса

Рекомендации по макетированию Material Design определяют области для панелей приложений, навигации и контента. Обычно первые два — это постоянные элементы пользовательского интерфейса, находящиеся в корне иерархии представлений (или очень близко к ним). Обратите внимание, что «постоянный» не обязательно означает, что представление всегда видимо, а скорее означает, что оно остается на месте, в то время как другие представления контента могут перемещаться или изменяться. Например, элемент навигации может находиться в выдвижном ящике за пределами экрана, но этот ящик всегда там.

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

<!-- res/layout/main_activity.xml -->

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- content view(s) -->

    <com.google.android.material.bottomappbar.BottomAppBar
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ... />
</androidx.constraintlayout.widget.ConstraintLayout>


<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        ... />

    <!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>

Содержание

Разместив постоянные элементы пользовательского интерфейса, используйте оставшееся пространство для содержимого, например, используя NavHostFragment с графом навигации вашего приложения. Дополнительную информацию см. в разделе «Навигация для адаптивных пользовательских интерфейсов» .

Убедитесь, что все данные доступны для разных размеров.

Сегодня большинство платформ приложений используют модель данных, отделенную от компонентов Android, вносящих вклад в пользовательский интерфейс (действия, фрагменты и представления). В Jetpack эту роль обычно выполняют модели ViewModel, которые имеют дополнительное преимущество, заключающееся в выживании при изменениях конфигурации (дополнительную информацию см. в разделе Обзор ViewModel ).

При реализации макета, адаптирующегося к разным размерам, может возникнуть соблазн использовать другую модель данных, основанную на текущем размере. Однако это противоречит принципу однонаправленного потока данных. Данные должны передаваться вниз к представлениям, а такие события, как взаимодействие с пользователем, должны течь вверх. Создание зависимости в другом направлении, где модель данных зависит от конфигурации уровня пользовательского интерфейса, существенно усложняет это. Когда приложение меняет размер, вы должны учитывать преобразование из одной модели данных в другую.

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

Развернуть контент

Канонические макеты : Лента

Расширенное пространство может стать возможностью просто увеличить размер и переформатировать контент, чтобы он стал более доступным.

Увеличивайте коллекции. Многие приложения отображают коллекцию элементов в контейнере с прокруткой, например RecyclerView или ScrollView . Включение автоматического увеличения размера контейнера означает, что можно отобразить больше контента. Однако будьте осторожны, чтобы содержимое контейнера не было чрезмерно растянуто или искажено. Например, при использовании RecyclerView рассмотрите возможность использования другого менеджера макета, такого как GridLayoutManager , StaggeredGridLayoutManager или FlexboxLayout , если ширина не компактна.

Устройство в сложенном и развернутом виде, показывающее, как разные менеджеры макетов по-разному размещают приложение в зависимости от класса размера ширины.
Рисунок 2. Различные менеджеры компоновки для разных классов размеров окон.

Отдельные элементы также могут использовать другой размер или форму, чтобы отображать больше контента и легче различать границы элементов.

Подчеркните элемент героя. Если в макете есть определенный фокус, например изображение или видео, разверните его, когда окно приложения увеличится, чтобы удержать внимание пользователя. Другие вспомогательные элементы можно переставлять вокруг или под окном героя.

Существует много способов создания такого макета, но ConstraintLayout особенно подходит для этой цели, поскольку он предоставляет множество способов ограничить размер дочернего представления — в том числе в процентах или обеспечить соблюдение соотношения сторон — и позиционировать его дочерние элементы относительно самого себя или относительно другие дети. Узнайте больше обо всех этих возможностях в статье «Создание адаптивного пользовательского интерфейса с помощью ConstraintLayout» .

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

Расширяйте поля. Если пространство настолько велико, что вы не можете найти подходящее место даже после использования всего вашего контента, расширьте поля макета, чтобы контент оставался центрированным, а отдельные представления имели естественные размеры и расстояние между ними.

Альтернативно, полноэкранный компонент может трансформироваться в плавающий диалоговый пользовательский интерфейс. Это особенно хорошо подходит, когда этому компоненту требуется исключительное внимание для выполнения непосредственной задачи пользователя, например составления электронного письма или создания события календаря.

Стандартный телефон, отображающий диалоговое окно в полноэкранном режиме, и развернутый складной телефон, отображающий тот же диалог в виде плавающего окна.
Рисунок 3. Полноэкранное диалоговое окно, преобразованное в стандартное диалоговое окно средней и расширенной ширины.

Добавить контент

Канонические макеты : вспомогательная панель, подробный список.

Используйте вспомогательную панель. Вспомогательная панель представляет дополнительный контент или контекстные действия, связанные с основным контентом, например комментарии в документе или элементы в списке воспроизведения. Обычно они используют нижнюю треть экрана для увеличения высоты или последнюю треть для увеличения ширины.

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

  • Боковой ящик на задней кромке с использованием DrawerLayout
  • Нижний ящик с использованием BottomSheetBehavior
  • Меню или всплывающее окно доступны при нажатии на значок меню.
Рисунок 4. Альтернативные способы представления дополнительного контента на вспомогательной панели.

Создайте двухпанельный макет. На больших экранах может отображаться комбинация функций, которые обычно отображаются отдельно на экранах меньшего размера. Распространенным шаблоном взаимодействия во многих приложениях является отображение списка элементов, например контактов или результатов поиска, и переключение на подробную информацию об элементе при его выборе. Вместо того, чтобы увеличивать список для больших экранов, используйте подробное представление списка, чтобы показать обе функции рядом в двухпанельном макете. В отличие от вспомогательной панели, панель сведений в представлении с подробными сведениями представляет собой отдельный элемент, который может отображаться независимо на экранах меньшего размера.

Используйте специальный виджет SlidingPaneLayout для реализации подробного представления списка. Этот виджет автоматически вычисляет, достаточно ли места для отображения обеих панелей вместе, на основе значения layout_width , указанного для двух панелей, а любое оставшееся пространство можно распределить с помощью layout_weight . Если места недостаточно, каждая панель использует всю ширину макета, а панель сведений либо выдвигается за пределы экрана, либо находится поверх панели списка.

SlidingPaneLayout показывает обе панели макета списка на устройстве с широким дисплеем.
Рис. 5. SlidingPaneLayout, показывающий две панели увеличенной ширины и одну панель компактной ширины.

Создание макета с двумя панелями содержит дополнительные сведения об использовании SlidingPaneLayout . Также обратите внимание, что этот шаблон может повлиять на структуру вашего графа навигации (см. Навигация для адаптивных пользовательских интерфейсов ).

Дополнительные ресурсы

{% дословно %} {% дословно %} {% дословно %} {% дословно %}