Column — to wbudowany komponent Composable Jetpack Compose z pakietu compose.foundation.layout, który układa elementy potomne pionowo, jeden pod drugim. Column jest odpowiednikiem LinearLayout z orientacją pionową ze starego systemu View, ale w przeciwieństwie do niego używa deklaratywnego opisu i automatycznie reaguje na zmiany stanu. Według Google Android Developers, 2026, Column jest jednym z trzech podstawowych kontenerów obok Row i Box.
Najważniejsze
Column — to funkcja Composable, która przyjmuje opcjonalne parametry: modifier, verticalArrangement, horizontalAlignment oraz content — lambdę z ColumnScope. Wewnątrz Column funkcje Composable potomne są układane od góry do dołu w kolejności deklaracji. Wysokość Column jest równa sumie wysokości elementów potomnych plus przestrzeń określona przez Arrangement. Szerokość — według maksymalnej szerokości elementu potomnego z uwzględnieniem Alignment.
Column jest niewidocznym kontenerem: nie ma własnego tła ani obramowania domyślnie. Jeśli potrzebne jest tło — dodaj Modifier.background() do samej Column. W przeciwieństwie do LazyColumn, Column wyświetla wszystkie elementy potomne jednocześnie i nie obsługuje wirtualizacji. Oznacza to, że Column nadaje się tylko do małych zestawów danych — do 10-15 elementów. Do długich list używaj LazyColumn.
ColumnScope — to receiver dla lambdy content w Column. Udostępnia dodatkowe modyfikatory, które działają tylko wewnątrz Column: weight(), align(), alignByBaseline(). Te modyfikatory nie mają sensu poza Column, ponieważ opierają się na specyfice pionowego układania. Na przykład Modifier.align(Alignment.CenterHorizontally) wyrównuje element potomny do środka Column w poziomie.
VerticalArrangement określa, jak rozkłada się pionowa przestrzeń między elementami. Dostępne wartości: Arrangement.Top (domyślnie), Bottom, Center, SpaceBetween, SpaceEvenly, SpaceAround. Jeśli wysokość Column jest większa niż suma wysokości elementów, Arrangement rozdziela wolną przestrzeń. Jeśli elementy zajmują całą wysokość — Arrangement nie ma wpływu.
HorizontalAlignment ustawia wyrównanie każdego elementu potomnego w poziomie. Alignment.Start (domyślnie, LTR), CenterHorizontally, End. Alignment działa na każdy element niezależnie: jeśli jeden element jest wąski, a drugi szeroki — pierwszy zostanie wyrównany, drugi może wyjść poza granice Column. Alignment działa tylko jeśli Column ma stałą szerokość lub fillMaxWidth.
Modifier dla Column: Column przyjmuje Modifier, który jest stosowany do samego kontenera. Modifier.fillMaxWidth(), fillMaxHeight(), size(), padding() — wszystkie standardowe modyfikatory działają. Cecha: Modifier.height(IntrinsicSize.Min) zmusza Column do obliczenia minimalnej wysokości na podstawie elementów potomnych z uwzględnieniem Intrinsic measurement.
@Composable
fun ColumnArrangementDemo() {
Column(
modifier = Modifier.fillMaxSize().background(Color(0xFFF5F5F5)),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Góra", modifier = Modifier.background(Color.Cyan))
Text("Środek", modifier = Modifier.background(Color.Magenta))
Text("Dół", modifier = Modifier.background(Color.Yellow))
}
}
// IntrinsicSize: Column dostosowuje wysokość do treści
@Composable
fun IntrinsicColumn() {
Column(
modifier = Modifier
.height(IntrinsicSize.Min)
.width(200.dp)
) {
Text("Krótki tekst")
Text("Bardzo długi tekst, który zawija się w kolumnie")
}
}
| Arrangement | Zachowanie |
|---|---|
| Arrangement.Top | Elementy dociśnięte do góry, wolna przestrzeń na dole |
| Arrangement.Center | Elementy na środku, przestrzeń dzielona równo u góry i na dole |
| Arrangement.SpaceBetween | Pierwszy element u góry, ostatni na dole, pozostałe równomiernie |
| Arrangement.SpaceEvenly | Równe odstępy między wszystkimi elementami i krawędziami |
| Arrangement.SpaceAround | Równe odstępy między elementami, połowiczne przy krawędziach |
Modifier.weight() — to modyfikator ColumnScope, który rozdziela wolną pionową przestrzeń między elementami Column proporcjonalnie do określonych wag. Jeśli Column zajmuje 400dp wysokości, a elementy potomne łącznie — 100dp, to pozostałe 300dp jest dzielone między elementy z weight. Element z weight(2f) otrzyma dwa razy więcej przestrzeni niż element z weight(1f).
fill — drugi parametr weight: weight(weight: Float, fill: Boolean = true). Jeśli fill = true (domyślnie), element rozciąga się na całą dostępną wysokość. Jeśli fill = false — element zajmuje tylko swoją intrinsic-wysokość, a pozostała przestrzeń pozostaje pusta. Jest to przydatne, gdy element ma być dociśnięty do jednej strony, ale weight określa tylko proporcję rozkładu pustego miejsca.
Ograniczenia weight: weight działa tylko w Column ze stałą wysokością lub fillMaxHeight(). Jeśli wysokość Column jest określona przez elementy potomne (wrap content), wagi nie mają sensu — nie ma wolnej przestrzeni do rozdzielenia. Nie można również łączyć weight z Modifier.height() na tym samym elemencie — są one konfliktowe i weight jest ignorowane.
@Composable
fun WeightedColumn() {
Column(
modifier = Modifier.fillMaxHeight().width(300.dp)
) {
// Zajmuje 1/6 wysokości (waga 1 z sumy 1+2+3=6)
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.background(Color.Red)
)
// Zajmuje 2/6 wysokości
Box(
modifier = Modifier
.weight(2f)
.fillMaxWidth()
.background(Color.Green)
)
// Zajmuje 3/6 wysokości
Box(
modifier = Modifier
.weight(3f)
.fillMaxWidth()
.background(Color.Blue)
)
}
}
Column wyświetla wszystkie elementy potomne od razu. Jeśli elementów jest więcej niż 10-15, Column tworzy znaczące obciążenie dla kompozycji i pomiarów. LazyColumn, przeciwnie, renderuje tylko widoczne elementy i ponownie wykorzystuje niewidoczne. Do długich list, list z tysiącami elementów, nieskończonych list lub czatów — LazyColumn jest obowiązkowy.
Kiedy Column jest lepszy: ekrany z formularzami (3-10 pól), karty profilu, pionowe kolumny z ikonami, menu. Column obsługuje również IntrinsicSize, co jest przydatne do adaptacyjnej wysokości. Ponadto Column jest łatwiejszy w debugowaniu — nie ma wirtualizacji, wszystkie elementy są widoczne w Layout Inspector. Do statycznego UI Column jest właściwym wyborem.
LazyColumn zapewnia: item caching, key-based identity, animację dodawania/usuwania (animateItemPlacement), sticky headers. Jeśli lista zawiera elementy różnych typów (różne viewType) — używaj LazyColumn z sealed class w items. Column nie obsługuje sticky headers (trzeba je emulować przez scrollable Column). LazyColumn obsługuje również LazyVerticalGrid przy użyciu GridCells.
| Kryterium | Column | LazyColumn |
|---|---|---|
| Liczba elementów | Do 10-15 | Dowolna |
| Wydajność | Zawsze renderuje wszystkie | Tylko widoczne + buffer |
| Scrolling | Przez Modifier.verticalScroll | Wbudowany |
| IntrinsicSize | Obsługuje | Nie obsługuje |
| Sticky headers | Nie (emulacja) | Tak (stickyHeader) |
| Animacja elementów | Brak wbudowanej | animateItemPlacement |
Rozważmy ekran profilu użytkownika, gdzie Column jest używany jako główny kontener dla awatara, nazwy, bio i przycisków akcji. Tutaj Column z IntrinsicSize.Min dostosowuje się do treści, a weight jest stosowany do rozkładu przestrzeni między sekcjami.
@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)
) {
// Awatar
Icon(
imageVector = Icons.Default.AccountCircle,
contentDescription = "Avatar",
modifier = Modifier.size(64.dp)
)
// Nazwa
Text(name, style = MaterialTheme.typography.headlineSmall)
// Bio
Text(bio, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 4.dp))
// Przyciski akcji
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.padding(top = 12.dp)
) {
Button(onClick = { }) { Text("Wiadomość") }
OutlinedButton(onClick = { }) { Text("Obserwuj") }
}
}
}
}
W przykładzie Column używa Arrangement.spacedBy(8.dp) dla równomiernych odstępów między elementami. horizontalAlignment = CenterHorizontally centruje awatar, nazwę i bio. Row wewnątrz Column — zagnieżdżony kontener dla przycisków w jednym rzędzie. Taka kombinacja Column (pionowe ułożenie) i Row (poziome) to typowy wzorzec budowania UI w Compose.
Często zadawane pytania
Column renderuje wszystkie elementy potomne od razu, co przy 100+ elementach powoduje spadek FPS. LazyColumn renderuje tylko widoczne elementy + buffer (zwykle 3-5 ekranów). Do statycznych ekranów z 3-10 elementami Column jest szybszy, ponieważ nie ma narzutu wirtualizacji.
Dodaj Modifier.verticalScroll(rememberScrollState()) do Column. To czyni Column przewijalną, ale nie daje wirtualizacji — wszystkie elementy nadal renderują się od razu. Do długich przewijalnych list używaj LazyColumn.
Tak, zagnieżdżanie Row/Column to normalna praktyka. Łącząc dwa kontenery, można budować złożone siatki. Należy jednak unikać głębokiego zagnieżdżania (4+ poziomów) bez potrzeby — zwiększa to liczbę pomiarów LayoutNode i spowalnia kompozycję.
Użyj Modifier.fillMaxWidth() na każdym elemencie potomnym. Jeśli Column ma Modifier.fillMaxWidth(), wszystkie elementy potomne z fillMaxWidth() rozciągną się na całą szerokość. Alternatywa: Modifier.weight(1f) w ColumnScope, jeśli Column znajduje się w stałym kontenerze.
Arrangement.spacedBy(space) dodaje stały odstęp między każdymi dwoma sąsiednimi elementami. W przeciwieństwie do SpaceBetween/SpaceAround, spacedBy nie rozciąga elementów — odstęp jest stały, a pozostała przestrzeń pozostaje na końcu Column. spacedBy nie dodaje odstępu przed pierwszym i po ostatnim elemencie.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również