Column: вертикальное расположение и настройка контейнера в Compose

Автор: IT Sectr Опубликовано: 2026-06-28 Время чтения: 8 мин

Column — это встроенный Composable-компонент Jetpack Compose из пакета compose.foundation.layout, который располагает дочерние элементы вертикально, один под другим. Column является аналогом LinearLayout с вертикальной ориентацией из старой View-системы, но в отличие от неё использует декларативное описание и автоматически реагирует на изменения состояния. По данным Google Android Developers, 2026, Column — один из трёх базовых контейнеров наряду с Row и Box.

Главное

  • Column располагает элементы вертикально с настройкой Arrangement и Alignment
  • Arrangement определяет распределение пространства между элементами по вертикали
  • Alignment задаёт горизонтальное выравнивание каждого элемента внутри Column
  • Вес (weight) распределяет свободное пространство пропорционально между элементами
  • IntrinsicSize позволяет Column подстраивать размер под минимальную/максимальную ширину дочерних

Что такое Column в Jetpack Compose

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 по горизонтали.

Параметры Column: Arrangement, Alignment, Modifier

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.

kotlin
@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Равные промежутки между элементами, половинные по краям

Column weight: распределение пространства между элементами

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 игнорируется.

kotlin
@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 vs LazyColumn: когда что использовать

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.

КритерийColumnLazyColumn
Количество элементовДо 10-15Любое
ПроизводительностьВсегда рендерит всеТолько видимые + buffer
ScrollingЧерез Modifier.verticalScrollВстроенный
IntrinsicSizeПоддерживаетНе поддерживает
Sticky headersНет (эмуляция)Да (stickyHeader)
Анимация элементовНет встроеннойanimateItemPlacement

Практические примеры использования Column

Рассмотрим экран профиля пользователя, где Column используется как основной контейнер для аватарки, имени, bio и кнопок действий. Здесь Column с IntrinsicSize.Min подстраивается под контент, а weight применяется для распределения пространства между секциями.

kotlin
@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 отличается от LazyColumn по производительности?

Column рендерит все дочерние элементы сразу, что при 100+ элементах вызывает падение FPS. LazyColumn рендерит только видимые элементы + buffer (обычно 3-5 экранов). Для статических экранов с 3-10 элементами Column быстрее, так как нет overhead виртуализации.

Как сделать Column прокручиваемой?

Добавьте Modifier.verticalScroll(rememberScrollState()) к Column. Это делает Column скроллируемой, но не даёт виртуализации — все элементы по-прежнему рендерятся сразу. Для длинных скроллируемых списков используйте LazyColumn.

Можно ли вложить Row в Column и Column в Row?

Да, вложенность Row/Column — нормальная практика. Комбинируя два контейнера, можно строить сложные сетки. Однако избегайте глубокой вложенности (4+ уровня) без необходимости — это увеличивает количество измерений LayoutNode и замедляет композицию.

Как сделать одинаковую ширину всех элементов в Column?

Используйте Modifier.fillMaxWidth() на каждом дочернем элементе. Если Column имеет Modifier.fillMaxWidth(), все дочерние с fillMaxWidth() растянутся на всю ширину. Альтернатива: Modifier.weight(1f) в ColumnScope, если Column находится в фиксированном контейнере.

Как работает spacedBy в Column?

Arrangement.spacedBy(space) добавляет фиксированный отступ между каждыми двумя соседними элементами. В отличие от SpaceBetween/SpaceAround, spacedBy не растягивает элементы — отступ фиксированный, а остальное пространство остаётся в конце Column. spacedBy не добавляет отступ перед первым и после последнего элемента.

Итоги

  • Column — базовый вертикальный контейнер Compose для размещения элементов сверху вниз
  • Arrangement управляет распределением пространства (Top, Center, SpaceBetween, spacedBy)
  • Alignment задаёт горизонтальное выравнивание каждого дочернего элемента
  • Weight распределяет свободное пространство пропорционально между элементами
  • Column vs LazyColumn: Column для 3-10 элементов, LazyColumn для длинных списков
  • IntrinsicSize позволяет Column подстраивать высоту под минимальное измерение дочерних
  • Рекомендация: используйте spacedBy для отступов между элементами вместо padding на каждом

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также