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 действа на всеки елемент независимо: ако един елемент е тесен, а друг широк — първият ще бъде подравнен, вторият може да излезе извън границите на 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("Горе", modifier = Modifier.background(Color.Cyan))
        Text("Среда", modifier = Modifier.background(Color.Magenta))
        Text("Долу", modifier = Modifier.background(Color.Yellow))
    }
}

    // IntrinsicSize: Column настройва височината спрямо съдържанието
@Composable
fun IntrinsicColumn() {
    Column(
        modifier = Modifier
            .height(IntrinsicSize.Min)
            .width(200.dp)
    ) {
        Text("Кратък текст")
        Text("Много дълъг текст, който ще се увие в колоната")
    }
}
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)
    ) {
        // Заема 1/6 от височината (тегло 1 от сбор 1+2+3=6)
        Box(
            modifier = Modifier
                .weight(1f)
                .fillMaxWidth()
                .background(Color.Red)
        )
        // Заема 2/6 от височината
        Box(
            modifier = Modifier
                .weight(2f)
                .fillMaxWidth()
                .background(Color.Green)
        )
        // Заема 3/6 от височината
        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, идентичност базирана на ключ, анимация на добавяне/премахване (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 се използва като основен контейнер за аватар, име, био и бутони за действия. Тук 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)
        ) {
            // Аватар
            Icon(
                imageVector = Icons.Default.AccountCircle,
                contentDescription = "Avatar",
                modifier = Modifier.size(64.dp)
            )
            // Име
            Text(name, style = MaterialTheme.typography.headlineSmall)
            // Био
            Text(bio, style = MaterialTheme.typography.bodyMedium,
                modifier = Modifier.padding(top = 4.dp))
            // Бутони за действия
            Row(
                horizontalArrangement = Arrangement.spacedBy(12.dp),
                modifier = Modifier.padding(top = 12.dp)
            ) {
                Button(onClick = { }) { Text("Съобщение") }
                OutlinedButton(onClick = { }) { Text("Следване") }
            }
        }
    }
}

В примера Column използва Arrangement.spacedBy(8.dp) за равномерни разстояния между елементите. horizontalAlignment = CenterHorizontally центрира аватара, името и био. 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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също