Как настроить вставки окон

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

Обработка вставок с помощью модификаторов отступов или размеров

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

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

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

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

Все эти типы вставок анимируются автоматически с помощью анимаций IME, перенесенных в API 21. Поэтому все макеты, использующие эти отступы, также автоматически анимируются при изменении значений отступов.

Есть три способа обработки вставок для корректировки макетов Composable:

Модификаторы полей

Modifier.windowInsetsPadding(windowInsets: WindowInsets) применяет заданные вставки окна в качестве отступов, действуя так же, как Modifier.padding. Например, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) применяет безопасные вставки для рисования в качестве отступов со всех четырех сторон.

Также есть несколько встроенных служебных методов для наиболее распространенных типов вставок. Modifier.safeDrawingPadding() – один из таких методов, эквивалентный Modifier.windowInsetsPadding(WindowInsets.safeDrawing). В таблице ниже перечислены встроенные модификаторы отступов и тип WindowInsets, который применяется каждым из них.

Modifier.safeDrawingPadding()

WindowInsets.safeDrawing

Modifier.safeGesturesPadding()

WindowInsets.safeGestures

Modifier.safeContentPadding()

WindowInsets.safeContent

Modifier.statusBarsPadding()

WindowInsets.statusBars

Modifier.navigationBarsPadding()

WindowInsets.navigationBars

Modifier.captionBarPadding()

WindowInsets.captionBar

Modifier.systemBarsPadding()

WindowInsets.systemBars

Modifier.imePadding()

WindowInsets.ime

Modifier.systemGesturesPadding()

WindowInsets.systemGestures

Modifier.mandatorySystemGesturesPadding()

WindowInsets.mandatorySystemGestures

Modifier.displayCutoutPadding()

WindowInsets.displayCutout

Modifier.waterfallPadding()

WindowInsets.waterfall

Подробнее о типах вставок…

Модификаторы размера вставки

Следующие модификаторы применяют количество вставок окна, устанавливая размер компонента равным размеру вставок:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

Применяет начальную сторону windowInsets в качестве ширины (например, Modifier.width).

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Применяет конечную сторону windowInsets в качестве ширины (например, Modifier.width).

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Применяет верхнюю сторону windowInsets в качестве высоты (например, Modifier.height).

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Применяет нижнюю сторону windowInsets в качестве высоты (например, Modifier.height).

Эти модификаторы особенно полезны для изменения размера Spacer, который занимает пространство вставок:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

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

Модификаторы отступов (windowInsetsPadding и вспомогательные элементы, такие как safeDrawingPadding) автоматически используют часть вставок, которые применяются в качестве отступов. При углублении в дерево композиции вложенные модификаторы отступов и размеров знают, что часть отступов уже была использована внешними модификаторами, и не используют одну и ту же часть отступов более одного раза, что привело бы к слишком большому дополнительному пространству.

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

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

Рассмотрим тот же пример с LazyColumn, что и ранее. Размер LazyColumn изменяется с помощью модификатора imePadding. Последний элемент в LazyColumn имеет высоту, равную высоте нижней части системных строк:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Когда редактор метода ввода закрыт, imePadding() не применяет отступы. В результате отступы не используются, а высота Spacer соответствует нижним системным строкам.

Когда открывается IME, его вставки анимируются в соответствии с размером IME, а модификатор imePadding() начинает применять нижний отступ, чтобы изменить размер LazyColumn по мере открытия IME. По мере того как модификатор imePadding() начинает применять нижний отступ, он также начинает использовать это количество вставок. Поэтому высота Spacer начинает уменьшаться, так как часть интервала для системных строк уже применена модификатором imePadding(). Когда модификатор imePadding() применяет нижний отступ, который больше системных строк, высота Spacer равна нулю.

Когда IME закрывается, изменения происходят в обратном порядке: Spacer расширяется от нулевой высоты, поскольку imePadding() применяется меньше, чем нижние системные строки. Наконец, когда IME полностью скрывается, высота Spacer совпадает с высотой системных строк.

Рисунок 2. Ленивый столбец от края до края с TextField.

Такое поведение достигается за счет взаимодействия между всеми модификаторами windowInsetsPadding, и на него можно повлиять несколькими другими способами.

Modifier.consumeWindowInsets(insets: WindowInsets) также использует вставки так же, как Modifier.windowInsetsPadding, но не применяет их в качестве отступов. Это полезно в сочетании с модификаторами размера вставок, чтобы указать дочерним элементам, что определенное количество вставок уже использовано:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) работает аналогично версии с аргументом WindowInsets, но принимает произвольный PaddingValues. Это полезно, чтобы сообщать дочерним элементам, когда отступы или интервалы предоставляются не модификаторами отступов, а другим механизмом, например обычным Modifier.padding или разделителями фиксированной высоты:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

Если вам нужны необработанные вставки окна без использования, используйте значения WindowInsets напрямую или WindowInsets.asPaddingValues(), чтобы вернуть PaddingValues вставок, на которые не влияет использование. Однако из-за следующих предостережений предпочитайте использовать модификаторы заполнения вставок окна и модификаторы размера вставок окна везде, где это возможно.

Этапы вставки и Jetpack Compose

Compose использует базовые основные API AndroidX для обновления и анимации вставок, которые используют базовые API платформы, управляющие вставками. Из-за такого поведения платформы вставки имеют особое отношение к фазам Jetpack Compose.

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