Разберем всю иерархию: от базовых строительных блоков до мощных инструментов для сложных экранов.
Column() — Вертикальный стек
Располагает элементы друг под другом, сверху вниз. Это прямой аналог
LinearLayout(vertical).Для чего нужен:
- Формы регистрации и экраны настроек.
- Ленты постов, где каждый элемент идет за другим.
- Группировка заголовка, текста и кнопки.
Пример:
ВыделитьKotlin
@Composable
fun UserProfile() {
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally // Центрируем всё по ширине
) {
Text(text = "Алексей", style = MaterialTheme.typography.headlineSmall)
Text(text = "@prizrak_dev", color = Color.Gray)
Spacer(modifier = Modifier.height(12.dp)) // Пустое пространство
Button(onClick = { /* ... */ }) { Text("Написать") }
}
}Row() — Горизонтальный стек
Располагает элементы слева направо. Аналог
LinearLayout(horizontal).Для чего нужен:
- Элементы меню (иконка + текст).
- Панели инструментов (Toolbar).
- Кнопки, где текст и иконка стоят в ряд.
Пример:
ВыделитьKotlin
@Composable
fun MessageItem() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically // Выравниваем по центру высоты
) {
Icon(Icons.Default.Email, contentDescription = null)
Spacer(modifier = Modifier.width(8.dp)) // Отступ
Text(text = "Новое сообщение")
}
}Box() — Наложение
Накладывает элементы друг на друга. Порядок важен: элементы, написанные в коде ниже, оказываются поверх предыдущих. Аналог
FrameLayout.Для чего нужен:
- Значки уведомлений на иконках (Бейджи).
- Градиентная подложка поверх изображения.
- Центрирование одного элемента по центру экрана.
Пример:
ВыделитьKotlin
@Composable
fun ProfileWithBadge() {
Box(contentAlignment = Alignment.TopEnd) {
// Нижний слой
Image(painter = painterResource(id = R.drawable.avatar),
contentDescription = "Аватар",
modifier = Modifier.size(64.dp))
// Верхний слой (поверх аватара)
Box(
modifier = Modifier
.size(16.dp)
.background(Color.Red, CircleShape)
.border(2.dp, Color.White, CircleShape)
)
}
}LazyColumn() и LazyRow() — Ленивые списки
Самые важные контейнеры для производительности. Они создают элементы только тогда, когда они появляются на экране.
Для чего нужен:
- Чаты, ленты новостей, списки товаров.
- Любые экраны с большим количеством данных.
Важно: Никогда не используйте обычный Column для списка из 50+ элементов — приложение зависнет. Используйте LazyColumn.
Пример:
ВыделитьKotlin
@Composable
fun ChatHistory(messages: List<String>) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(bottom = 70.dp) // Отступ под поле ввода
) {
items(messages) { msg ->
Text(text = msg, modifier = Modifier.padding(8.dp))
}
}
}Scaffold() — Каркас Material Design
Это не просто контейнер, а готовый шаблон экрана по правилам Google Material. Он предоставляет «слоты» для стандартных элементов.
Для чего нужен:
- Чтобы быстро собрать экран с TopAppBar, BottomAppBar и FloatingActionButton (FAB).
- Для удобной работы с Snackbar.
- Он автоматически учитывает «вырезы» экрана (Камера, навигационная панель).
Пример:
ВыделитьKotlin
@Composable
fun HomeScreen() {
Scaffold(
topBar = { Text("Rush Messenger", Modifier.fillMaxWidth().padding(16.dp)) },
floatingActionButton = {
FloatingActionButton(onClick = {}) { Icon(Icons.Default.Add, null) }
}
) { innerPadding ->
// Основной контент. Scaffold сам передает отступы, чтобы контент не ушел под FAB.
LazyColumn(contentPadding = innerPadding) {
items(100) { Text("Сообщение #$it") }
}
}
}ConstraintLayout() — Сложные связи
Мощный инструмент для создания сложных интерфейсов без глубокой вложенности Column в Row. Позволяет привязывать границы одного элемента к границам другого.
Для чего нужен:
- Сложные карточки товаров.
- Экраны, где элементы должны быть выровнены относительно друг друга по диагонали или крест-накрест.
- Когда
Column/Rowтребуют слишком много вложенности.
Пример:
ВыделитьKotlin
@Composable
fun ComplexCard() {
ConstraintLayout(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
val (title, subtitle, button) = createRefs()
Text("Важный заголовок", Modifier.constrainAs(title) {
top.linkTo(parent.top)
start.linkTo(parent.start)
})
Text("Описание", Modifier.constrainAs(subtitle) {
top.linkTo(title.bottom, 8.dp)
start.linkTo(title.start)
end.linkTo(button.start, 8.dp) // Текст не заходит на кнопку
})
Button(onClick = {}, Modifier.constrainAs(button) {
end.linkTo(parent.end)
top.linkTo(title.top)
bottom.linkTo(title.bottom)
}) {
Text("Действие")
}
}
}Layout() — Создание своего контейнера
Это фундамент Compose. Если вам не подходит ни один стандартный контейнер, вы можете написать свой. С помощью
Layout вы вручную измеряете и расставляете дочерние элементы.Для чего нужен:
- Создание уникальных макетов (например, круговое меню или верстка в виде дуги).
- Максимальная оптимизация, если стандартные контейнеры делают лишнюю работу.
Пример (Простейший Column своими руками):
ВыделитьKotlin
@Composable
fun MyOwnColumn(content: @Composable () -> Unit) {
Layout(content = content) { measurables, constraints ->
val placeables = measurables.map { it.measure(constraints) }
var height = placeables.sumOf { it.height }
layout(constraints.maxWidth, height) {
var y = 0
placeables.forEach { placeable ->
placeable.place(x = 0, y = y)
y += placeable.height
}
}
}
}Итог: Когда и что использовать?
- Column: Простой список сверху вниз.
- Row: Панель инструментов или меню слева направо.
- Box: Иконка поверх картинки или центрирование одного элемента.
- LazyColumn: Чаты, ленты, каталоги (любые большие списки).
- Scaffold: Стандартный экран приложения с панелью сверху и кнопкой FAB.
- ConstraintLayout: Сложные связи между элементами, чтобы избежать вложенности.
- Layout: Когда нужно создать что-то, чего нет в стандартной библиотеке.