Column — это встроенный Composable-компонент Jetpack Compose из пакета compose.foundation.layout, который располагает дочерние элементы вертикально, один под другим. Column является аналогом LinearLayout с вертикальной ориентацией из старой View-системы, но в отличие от неё использует декларативное описание и автоматически реагирует на изменения состояния. По данным Google Android Developers, 2026, Column — один из трёх базовых контейнеров наряду с Row и Box.
Главное
Column — это Composable-функция, которая принимает необязательные параметры: modifier, verticalArrangement, horizontalAlignment и content — лямбду с ColumnScope. Внутри Column дочерние Composable-функции располагаются сверху вниз в порядке объявления. Высота Column равна сумме высот дочерних элементов плюс пространство, заданное Arrangement. Ширина — по максимальной ширине дочернего элемента с учётом Alignment.
Column — невидимый контейнер: он не имеет собственного фона или границы по умолчанию. Если нужен фон — добавьте Modifier.background() к самой Column. В отличие от LazyColumn, Column отображает все дочерние элементы одновременно и не поддерживает виртуализацию. Это значит, что Column подходит только для небольших наборов данных — до 10-15 элементов. Для длинных списков используйте LazyColumn.
ColumnScope — это receiver для content-лямбды Column. Он предоставляет дополнительные модификаторы, которые работают только внутри Column: weight(), align(), alignByBaseline(). Эти модификаторы не имеют смысла вне Column, так как они опираются на специфику вертикального расположения. Например, Modifier.align(Alignment.CenterHorizontally) выравнивает дочерний элемент по центру Column по горизонтали.
VerticalArrangement определяет, как распределяется вертикальное пространство между элементами. Доступные значения: Arrangement.Top (по умолчанию), Bottom, Center, SpaceBetween, SpaceEvenly, SpaceAround. Если высота Column больше суммы высот элементов, Arrangement распределяет свободное пространство. Если элементы занимают всю высоту — Arrangement не влияет.
HorizontalAlignment задаёт выравнивание каждого дочернего элемента по горизонтали. Alignment.Start (по умолчанию, LTR), CenterHorizontally, End. Alignment действует на каждый элемент независимо: если один элемент narrow, а другой wide — первый будет выровнен, второй может выйти за границы Column. Alignment работает только если Column имеет фиксированную ширину или fillMaxWidth.
Modifier для Column: Column принимает Modifier, который применяется к самому контейнеру. Modifier.fillMaxWidth(), fillMaxHeight(), size(), padding() — все стандартные модификаторы работают. Особенность: Modifier.height(IntrinsicSize.Min) заставляет Column вычислять минимальную высоту на основе дочерних элементов с учётом Intrinsic measurement.
@Composable
fun ColumnArrangementDemo() {
Column(
modifier = Modifier.fillMaxSize().background(Color(0xFFF5F5F5)),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Top", modifier = Modifier.background(Color.Cyan))
Text("Middle", modifier = Modifier.background(Color.Magenta))
Text("Bottom", modifier = Modifier.background(Color.Yellow))
}
}
// IntrinsicSize: Column adjusts height to content
@Composable
fun IntrinsicColumn() {
Column(
modifier = Modifier
.height(IntrinsicSize.Min)
.width(200.dp)
) {
Text("Short text")
Text("A very long text that will wrap inside the column")
}
}
| Arrangement | Поведение |
|---|---|
| Arrangement.Top | Элементы прижаты к верху, свободное пространство внизу |
| Arrangement.Center | Элементы по центру, пространство делится поровну сверху и снизу |
| Arrangement.SpaceBetween | Первый элемент вверху, последний внизу, остальные равномерно |
| Arrangement.SpaceEvenly | Равные промежутки между всеми элементами и краями |
| Arrangement.SpaceAround | Равные промежутки между элементами, половинные по краям |
Modifier.weight() — это модификатор ColumnScope, который распределяет свободное вертикальное пространство между элементами Column пропорционально указанным весам. Если Column занимает 400dp высоты, а дочерние элементы суммарно — 100dp, то оставшиеся 300dp делятся между weight-элементами. Элемент с weight(2f) получит вдвое больше пространства, чем элемент с weight(1f).
fill — второй параметр weight: weight(weight: Float, fill: Boolean = true). Если fill = true (по умолчанию), элемент растягивается на всю доступную высоту. Если fill = false — элемент занимает только свою intrinsic-высоту, а оставшееся пространство остаётся пустым. Это полезно, когда элемент должен быть прижат к одной стороне, но weight задаёт только пропорцию распределения пустого места.
Ограничения weight: weight работает только в Column с фиксированной высотой или fillMaxHeight(). Если высота Column определена дочерними элементами (wrap content), веса не имеют смысла — нет свободного пространства для распределения. Также weight нельзя комбинировать с Modifier.height() на том же элементе — они конфликтуют, и weight игнорируется.
@Composable
fun WeightedColumn() {
Column(
modifier = Modifier.fillMaxHeight().width(300.dp)
) {
// Takes 1/6 of height (weight 1 of sum 1+2+3=6)
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.background(Color.Red)
)
// Takes 2/6 of height
Box(
modifier = Modifier
.weight(2f)
.fillMaxWidth()
.background(Color.Green)
)
// Takes 3/6 of height
Box(
modifier = Modifier
.weight(3f)
.fillMaxWidth()
.background(Color.Blue)
)
}
}
Column отображает все дочерние элементы сразу. Если элементов больше 10-15, Column создаёт значительную нагрузку на композицию и измерение. LazyColumn, напротив, рендерит только видимые элементы и переиспользует невидимые. Для длинных списков, списков с тысячами элементов, бесконечных списков или чатов — LazyColumn обязателен.
Когда Column лучше: экраны с формами (3-10 полей), карточки профиля, вертикальные колонки с иконками, меню. Column также поддерживает IntrinsicSize, что полезно для адаптивной высоты. Кроме того, Column проще в отладке — нет виртуализации, все элементы видны в Layout Inspector. Для статического UI Column — правильный выбор.
LazyColumn даёт: item caching, key-based identity, анимацию добавления/удаления (animateItemPlacement), sticky headers. Если список содержит элементы разного типа (разные viewType) — используйте LazyColumn с sealed class в items. Column не поддерживает sticky headers (их нужно эмулировать через scrollable Column). Также LazyColumn поддерживает LazyVerticalGrid при использовании GridCells.
| Критерий | Column | LazyColumn |
|---|---|---|
| Количество элементов | До 10-15 | Любое |
| Производительность | Всегда рендерит все | Только видимые + buffer |
| Scrolling | Через Modifier.verticalScroll | Встроенный |
| IntrinsicSize | Поддерживает | Не поддерживает |
| Sticky headers | Нет (эмуляция) | Да (stickyHeader) |
| Анимация элементов | Нет встроенной | animateItemPlacement |
Рассмотрим экран профиля пользователя, где Column используется как основной контейнер для аватарки, имени, bio и кнопок действий. Здесь Column с IntrinsicSize.Min подстраивается под контент, а weight применяется для распределения пространства между секциями.
@Composable
fun UserProfileCard(name: String, bio: String) {
Card(
modifier = Modifier.fillMaxWidth().padding(16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Column(
modifier = Modifier.fillMaxWidth().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
// Avatar
Icon(
imageVector = Icons.Default.AccountCircle,
contentDescription = "Avatar",
modifier = Modifier.size(64.dp)
)
// Name
Text(name, style = MaterialTheme.typography.headlineSmall)
// Bio
Text(bio, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 4.dp))
// Action buttons
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.padding(top = 12.dp)
) {
Button(onClick = { }) { Text("Message") }
OutlinedButton(onClick = { }) { Text("Follow") }
}
}
}
}
В примере Column использует Arrangement.spacedBy(8.dp) для равномерных отступов между элементами. horizontalAlignment = CenterHorizontally центрирует аватарку, имя и bio. Row внутри Column — вложенный контейнер для кнопок в одну строку. Такая комбинация Column (вертикальное расположение) и Row (горизонтальное) — типовой паттерн построения UI в Compose.
Часто задаваемые вопросы
Column рендерит все дочерние элементы сразу, что при 100+ элементах вызывает падение FPS. LazyColumn рендерит только видимые элементы + buffer (обычно 3-5 экранов). Для статических экранов с 3-10 элементами Column быстрее, так как нет overhead виртуализации.
Добавьте Modifier.verticalScroll(rememberScrollState()) к Column. Это делает Column скроллируемой, но не даёт виртуализации — все элементы по-прежнему рендерятся сразу. Для длинных скроллируемых списков используйте LazyColumn.
Да, вложенность Row/Column — нормальная практика. Комбинируя два контейнера, можно строить сложные сетки. Однако избегайте глубокой вложенности (4+ уровня) без необходимости — это увеличивает количество измерений LayoutNode и замедляет композицию.
Используйте Modifier.fillMaxWidth() на каждом дочернем элементе. Если Column имеет Modifier.fillMaxWidth(), все дочерние с fillMaxWidth() растянутся на всю ширину. Альтернатива: Modifier.weight(1f) в ColumnScope, если Column находится в фиксированном контейнере.
Arrangement.spacedBy(space) добавляет фиксированный отступ между каждыми двумя соседними элементами. В отличие от SpaceBetween/SpaceAround, spacedBy не растягивает элементы — отступ фиксированный, а остальное пространство остаётся в конце Column. spacedBy не добавляет отступ перед первым и после последнего элемента.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также