Прямые ссылки на публичные уроки для быстрого старта и стабильной индексации lesson-страниц.
Мы уже умеем создавать собственные composable функции. Теперь разберём позиционирование элементов на экране.
В функции StudyAppHeader добавим второй текст — подзаголовок с меньшим размером шрифта и без паддинга:
Text( text = "AndroidSprint", fontSize = 26.sp, modifier = Modifier.padding(innerPadding) ) Text( text = "Изучение Kotlin & Android через практику", fontSize = 16.sp, )
В превью видно, что тексты наложились друг на друга — Jetpack Compose по умолчанию не знает, в каком порядке размещать элементы. Нам нужно явно задать размещение через специальные composable layout функции.
Оборачиваем оба текста в функцию Column — и они расположатся один под другим. Column принимает параметры для модификаций, выравнивания по вертикали и горизонтали, а последний параметр — лямбда, внутри которой размещаются дочерние composable функции.
Column { Text( text = "AndroidSprint", fontSize = 26.sp, modifier = Modifier.padding(innerPadding) ) Text( text = "Изучение Kotlin & Android через практику", fontSize = 16.sp, ) }
Заголовок располагается с системными паддингами, подзаголовок — ниже с уменьшенным шрифтом.
Предположим, что ниже в приложении должны располагаться кнопки навигации по разделам. Создадим для них отдельную функцию MainNavButtons() и продублируем её в превью по аналогии.
Для размещения элементов в ряд используется Row — работает так же, как Column, но располагает элементы горизонтально. Внутри размещаем три кнопки через Button.
Особенности компонента Button:
onClick обязателен, поэтому в качестве заглушки передаём пустую лямбду.Button принимает composable функции в контексте RowScope.() — сюда помещаем Text для надписи на кнопке. RowScope говорит о том, что внутри кнопки скрыт Row@Composable fun MainNavButtons() { Row { Button(onClick = { }) { Text(text = "Уроки") } Button(onClick = { }) { Text(text = "Тесты") } Button(onClick = { }) { Text(text = "Практика") } } }
setContentКнопки пока видны только в превью — в setContent функция MainNavButtons не вызывается. Добавим её. Без общего контейнера кнопки окажутся у самого края экрана, поскольку системный паддинг применён только к заголовку.
Создадим основной контейнер — Column в setContent с системным паддингом. Переносим innerPadding из заголовка на этот контейнер, а из StudyAppHeader параметр убираем — функция становится независимой.
Теперь все элементы внутри setContent автоматически:
1. располагаются друг под другом без наложения,
2. имеют системный отступ и не заезжают на статус-бар и навигационную панель.
Логика такова: создаём отдельные части экрана в виде пользовательских методов, затем компонуем их в основном контейнере в setContent.
Третий основной тип контейнера — Box. Это аналог FrameLayout из XML: позволяет размещать элементы внутри других или друг на друге. Если заменить Column в хедере на Box, тексты наложатся. Используется по ситуации.
Разберём параметры позиционирования на задаче: расположить тексты и кнопки по центру экрана.
В параметрах главного контейнера есть horizontalAlignment — по умолчанию Alignment.Start, поэтому элементы прижаты влево. Меняем на Alignment.CenterHorizontally.
Чтобы убедиться в эффекте, добавим фон колонке через модификатор background(Color.LightGray). Обнаружим, что ширина колонки по умолчанию равна ширине контента. Растянем её на весь экран через fillMaxWidth(). Если использовать fillMaxSize() — увидим, что системный паддинг работает и снизу.
setContent { Scaffold( content = { innerPadding: PaddingValues -> Column( modifier = Modifier .padding(innerPadding) .background(Color.LightGray) .fillMaxSize() , horizontalAlignment = Alignment.CenterHorizontally ) { StudyAppHeader() MainNavButtons() } } ) }
Зафиксируем мысль: Alignment задаёт положение элемента относительно границ контейнера — по центру, слева, справа и т.д.
Аналогичный параметр центрирования добавим и для колонки внутри хедера.
Второй параметр — Arrangement. Он управляет пространственным распределением элементов внутри контейнера. Для Column — verticalArrangement, для Row — horizontalArrangement. Значение Arrangement.Center смещает все элементы к центру.
Другие значения Arrangement:
Для визуального разделения заголовка и кнопок используем Spacer с модификатором height(30.dp).
На отдельный элемент Text можно повесить модификатор align. Например, Modifier.align(Alignment.End) сдвинет заголовок вправо внутри своего контейнера.
По умолчанию кнопки занимают только пространство под свой текст. Чтобы каждая кнопка занимала равную долю Row, применяем Modifier.weight(1f) — тогда три кнопки поделят ширину контейнера поровну.
Добавим горизонтальный отступ между кнопками: Modifier.padding(horizontal = 5.dp) для каждой кнопки. Сам Row также получает горизонтальный паддинг 5.dp, чтобы кнопки не сливались с краями экрана.
Принудительные размеры элемента задаются через модификаторы width и height. При их использовании fillMaxSize убираем — контейнер приобретёт форму заданного размера.
В следующем уроке рассмотрим тему модификаторов и аргументов composable функций.