В Compose элементы пользовательского интерфейса представлены компонуемыми функциями, которые при вызове генерируют фрагмент пользовательского интерфейса, который затем добавляется в дерево пользовательского интерфейса, отображаемое на экране. Каждый элемент пользовательского интерфейса имеет одного родительского элемента и потенциально множество дочерних элементов. Каждый элемент также располагается внутри своего родительского элемента, указывая его координату (x, y) и размер, определяемый параметрами width и height .
Родительские элементы определяют ограничения для своих дочерних элементов. Элементу предлагается определить свой размер в рамках этих ограничений. Ограничения ограничивают минимальную и максимальную width и height элемента. Если у элемента есть дочерние элементы, он может измерить каждый из них, чтобы определить его размер. После того, как элемент определит и сообщит свой размер, он сможет определить, как размещать свои дочерние элементы относительно себя, как подробно описано в разделе Создание пользовательских макетов .
Разметка каждого узла в дереве пользовательского интерфейса выполняется в три этапа. Каждый узел должен:
- Измерьте всех детей
- Определите свой собственный размер
- Поместите его детей
Использование областей действия определяет, когда можно измерять и размещать дочерние элементы. Измерение макета может выполняться только во время проходов измерения и макета, а размещение дочернего элемента возможно только во время проходов макета (и только после его измерения). Благодаря таким областям действия Compose, как MeasureScope и PlacementScope , это обеспечивается во время компиляции.
Используйте модификатор макета
Вы можете использовать модификатор layout для изменения способа измерения и расположения элемента. Layout — это лямбда-выражение; его параметры включают измеряемый элемент, передаваемый как measurable , и входящие ограничения этого компонуемого элемента, передаваемые как constraints . Пользовательский модификатор макета может выглядеть следующим образом:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Отобразите Text на экране и управляйте расстоянием от верхнего края до базовой линии первой строки текста. Именно это и делает модификатор paddingFromBaseline ; мы реализуем его здесь в качестве примера. Для этого используйте модификатор layout , чтобы вручную разместить компонуемый элемент на экране. Вот результат, когда верхний отступ Text установлен на 24.dp :

paddingFromBaseline .Вот код для создания такого интервала:
fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp ) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] != AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) } }
Вот что происходит в этом коде:
- В
measurableлямбда-параметре вы измеряетеText, представленный измеряемым параметром, путем вызоваmeasurable.measure(constraints). - Размер компонуемого элемента задаётся вызовом метода
layout(width, height), который также возвращает лямбда-выражение, используемое для размещения обёрнутых элементов. В данном случае это высота между последней базовой линией и добавленным верхним отступом. - Обёрнутые элементы размещаются на экране с помощью метода
placeable.place(x, y). Если обёрнутые элементы не размещены, они не будут видны. Положение по осиyсоответствует верхнему отступу: положению первой базовой линии текста.
Чтобы проверить, что это работает так, как и ожидалось, используйте этот модификатор в Text :
@Preview @Composable fun TextWithPaddingToBaselinePreview() { MyApplicationTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } } @Preview @Composable fun TextWithNormalPaddingPreview() { MyApplicationTheme { Text("Hi there!", Modifier.padding(top = 32.dp)) } }

Text , который можно составить, и просмотренный.Создавайте индивидуальные макеты
Модификатор layout изменяет только вызывающий компонуемый объект. Для измерения и компоновки нескольких компонуемых объектов используйте компонуемый объект Layout . Этот компонуемый объект позволяет вручную измерять и компоновать дочерние элементы. Все макеты более высокого уровня, такие как Column и Row , создаются с помощью компонуемого Layout .
В этом примере создается очень простая версия Column . Большинство пользовательских макетов следуют этому шаблону:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // measure and position children given constraints logic here // ... } }
Аналогично модификатору layout , measurables — это список дочерних элементов, которые необходимо измерить, а constraints — это ограничения родительского элемента. Следуя той же логике, что и раньше, MyBasicColumn можно реализовать следующим образом:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // Don't constrain child views further, measure them with given constraints // List of measured children val placeables = measurables.map { measurable -> // Measure each children measurable.measure(constraints) } // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // Track the y co-ord we have placed children up to var yPosition = 0 // Place children in the parent layout placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition) // Record the y co-ord placed up to yPosition += placeable.height } } } }
Дочерние компонуемые элементы ограничены ограничениями Layout (без ограничений minHeight ) и размещаются на основе yPosition предыдущего компонуемого элемента.
Вот как будет использоваться этот индивидуальный составной элемент:
@Composable fun CallingComposable(modifier: Modifier = Modifier) { MyBasicColumn(modifier.padding(8.dp)) { Text("MyBasicColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } }

Column .Направление макета
Измените направление макета компонуемого элемента, изменив локальное свойство композиции LocalLayoutDirection .
Если вы размещаете компонуемые элементы на экране вручную, LayoutDirection является частью LayoutScope модификатора layout или компонуемого элемента Layout .
При использовании layoutDirection размещайте компонуемые элементы с помощью place . В отличие от метода placeRelative , place не меняется в зависимости от направления макета (слева направо или справа налево).
Пользовательские макеты в действии
Узнайте больше о макетах и модификаторах в разделе «Основные макеты» в Compose и посмотрите на пользовательские макеты в действии в примерах Compose, которые создают пользовательские макеты .
Узнать больше
Чтобы узнать больше о пользовательских макетах в Compose, ознакомьтесь со следующими дополнительными ресурсами.
Видео
{% дословно %}Рекомендовано для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Внутренние измерения в макетах Compose
- Графика в Compose
- Модификаторы сочинения