Ответ
Layout — это низкоуровневая функция в Jetpack Compose, позволяющая создать кастомный лейаут с нуля. Она принимает content и измеряет/размещает его по своим правилам.
Пример:
@Composable
fun CustomLayout(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
content = content,
modifier = modifier
) { measurables, constraints ->
// 1. Измеряем дочерние элементы
val placeables = measurables.map { it.measure(constraints) }
// 2. Вычисляем размер лейаута
val width = placeables.sumOf { it.width }
val height = placeables.maxOfOrNull { it.height } ?: 0
// 3. Размещаем дочерние элементы
layout(width, height) {
var x = 0
placeables.forEach { placeable ->
placeable.placeRelative(x = x, y = 0)
x += placeable.width
}
}
}
}
Здесь мы создаем горизонтальный лейаут, размещая элементы друг за другом.
Ответ 18+ 🔞
Ну ты смотри, какие дела творятся. Вот сидишь ты, такой весь из себя современный разработчик, с джавой и котлином на короткой ноге, а тут бац — и тебе вдруг понадобилось нарисовать интерфейс, который стандартными штуками не соберёшь. Ёпта, ну и что делать? Правильно, лезть в дебри и писать свой лейаут с блэкджеком и... ну, сами понимаете.
Так вот, Layout в Compose — это, по сути, твой пропуск в этот адский цех. Функция низкоуровневая, голая, как сосиска. Берёшь её и с нуля начинаешь городить свой порядок. Никаких Row или Column тебе в помощь — только твой мозг, руки и эта самая Layout.
Смотри, как это выглядит, а то я чувствую, у тебя уже волнение ебать начинает подкатывать.
@Composable
fun CustomLayout(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
content = content,
modifier = modifier
) { measurables, constraints ->
// 1. Измеряем дочерние элементы
val placeables = measurables.map { it.measure(constraints) }
// 2. Вычисляем размер лейаута
val width = placeables.sumOf { it.width }
val height = placeables.maxOfOrNull { it.height } ?: 0
// 3. Размещаем дочерние элементы
layout(width, height) {
var x = 0
placeables.forEach { placeable ->
placeable.placeRelative(x = x, y = 0)
x += placeable.width
}
}
}
}
Видишь эту конструкцию? Это же, блядь, чистая магия, обёрнутая в синтаксис. Сейчас разжую.
Первым делом, ты объявляешь свою функцию. В неё прилетает content — это твои будущие детки, которые внутри этого лейаута будут сидеть. Дальше вызываешь Layout, суёшь туда этот контент и модификатор, а потом начинается самое интересное — лямбда.
В этой лямбде тебе на блюдечке приносят две штуки: measurables и constraints. Measurables — это список твоих детей, но ещё не измеренных, диких таких. А constraints — это ограничения от родителя, типа "сюда влезай, а дальше нельзя".
Дальше три шага, проще некуда, хоть и звучит страшно.
Шаг первый: измерение. Берёшь каждого ребёнка из measurables и говоришь ему: "Ну-ка, меряйся, хули ты тут стоишь!" — через it.measure(constraints). На выходе получаешь placeables — это уже измеренные сущности, с известными шириной и высотой, готовые к размещению.
Шаг второй: самоопределение. Тебе надо решить, какого же размера будет твой собственный лейаут. В примере выше — примитив до безобразия. Ширина — это сумма ширин всех детей. Высота — это высота самого высокого ребёнка. Получается такой горизонтальный ряд. Но тут-то и кроется вся сила: можешь вычислять размер как угодно, хоть по луне привязывай. Это твоё царство.
Шаг третий: расстановка по полочкам. Вызываешь layout(width, height), передав вычисленные размеры, и внутри уже начинаешь детей расставлять методом placeRelative. В примере просто ставят их в ряд, сдвигая x на ширину предыдущего. Но опять же — можешь хоть по кругу распихать, хоть в шахматном порядке. Полная воля.
Вот и вся наука. Выглядит, конечно, как инструкция к сборке космического корабля из говна и палок, но если вникнуть — логика проще пареной репы. Главное — не бздеть и попробовать. Сначала будет ощущение, что ты пытаешься засунуть диван в хрущёвский лифт, но потом втянешься. Удачи, чувак.