Используйте классы размеров окон

Попробуйте способ «Композиции»
Jetpack Compose — рекомендуемый набор инструментов для разработки пользовательского интерфейса для Android. Узнайте, как использовать классы размеров окон в Compose.

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

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

Рисунок 1. Представление классов размеров окон, основанных на ширине.
Рисунок 2. Представление классов размеров окон, основанных на высоте.

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

Размерная категория Точка останова Представление устройства
Компактная ширина ширина < 600dp 99,96% телефонов в портретном режиме
Средняя ширина 600dp ≤ ширина < 840dp 93,73% планшетов работают в портретном режиме.

большинство больших развернутых внутренних дисплеев в портретном режиме

Расширенная ширина 840dp ≤ ширина < 1200dp 97,22% планшетов расположены в альбомной ориентации.

Большинство больших развернутых внутренних дисплеев в альбомной ориентации имеют как минимум увеличенную ширину.

Большая ширина 1200dp ≤ ширина < 1600dp Большие планшетные дисплеи
Сверхбольшая ширина ширина ≥ 1600dp Настольные дисплеи
Компактная высота высота < 480dp 99,78% телефонов находятся в альбомной ориентации.
Средняя высота 480dp ≤ высота < 900dp 96,56% планшетов расположены в альбомной ориентации.

97,59% телефонов в портретном режиме

Увеличенная высота высота ≥ 900dp 94,25% планшетов в портретном режиме

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

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

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

Размеры окон соответствуют точкам перехода «компактный», «средний» и «расширенный» в рекомендациях по компоновке Material Design . Кроме того, добавлены точки перехода «большой» и «очень большой» для более точного соответствия настольным компьютерам и подключенным дисплеям.

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

Вы можете вычислить текущий WindowSizeClass с помощью функции WindowSizeClass#compute() предоставляемой библиотекой Jetpack WindowManager . В следующем примере показано, как вычислить класс размера окна и получать обновления при каждом изменении класса размера окна:

Котлин

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        val container: ViewGroup = binding.container

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(object : View(this) {
            override fun onConfigurationChanged(newConfig: Configuration?) {
                super.onConfigurationChanged(newConfig)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }

    private fun computeWindowSizeClasses() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        val width = metrics.bounds.width()
        val height = metrics.bounds.height()
        val density = resources.displayMetrics.density
        val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass
        // COMPACT, MEDIUM, or EXPANDED
        val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Ява

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        ViewGroup container = binding.container;

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(new View(this) {
            @Override
            protected void onConfigurationChanged(Configuration newConfig) {
                super.onConfigurationChanged(newConfig);
                computeWindowSizeClasses();
            }
        });

        computeWindowSizeClasses();
    }

    private void computeWindowSizeClasses() {
        WindowMetrics metrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this);

        int width = metrics.getBounds().width();
        int height = metrics.getBounds().height();
        float density = getResources().getDisplayMetrics().density;
        WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density);
        // COMPACT, MEDIUM, or EXPANDED
        WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass();
        // COMPACT, MEDIUM, or EXPANDED
        WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass();

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

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

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

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

Следующие шаги

Чтобы узнать больше о том, как использовать классы размеров окон для создания адаптивных макетов, см. следующие материалы:

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