Rows und Columns in Jetpack Compose
Lerne die grundlegenden Layout-Bausteine von Jetpack Compose kennen. Verstehe Arrangement und Alignment für präzise Benutzeroberflächen.
Wenn du mit Jetpack Compose Benutzeroberflächen für Android entwickelst, benötigst du Werkzeuge, um Text, Bilder und Schaltflächen strukturiert auf dem Bildschirm anzuordnen. Anstelle komplexer XML-Hierarchien nutzt du in Compose deklarative Funktionen, die exakt beschreiben, wie sich Elemente zueinander verhalten sollen. Die absoluten Grundlagen für diese visuelle Strukturierung bilden zwei Kernkomponenten: Rows und Columns. Diese beiden Layout-Primitive erlauben es dir, nahezu jedes denkbare Screendesign schrittweise aufzubauen, indem du sie gezielt kombinierst und über Parameter konfigurierst.
Was ist das?
In der deklarativen UI-Entwicklung mit Jetpack Compose sind Row und Column die primären Container-Funktionen, um andere Composable-Funktionen auf dem Bildschirm anzuordnen. Eine Row (Zeile) platziert alle in ihr enthaltenen Elemente horizontal nebeneinander. Eine Column (Spalte) ordnet ihre Kind-Elemente vertikal untereinander an. Sie bilden das Grundgerüst, durch das du die visuelle Struktur einer Anwendung definierst.
Früher, im traditionellen View-System von Android, hättest du für solche Aufgaben oft ein einzelnes LinearLayout verwendet und dessen Orientierung auf horizontal oder vertikal gesetzt. Jetpack Compose trennt diese Zuständigkeiten explizit in zwei separate Funktionen. Diese architektonische Entscheidung macht den Code nicht nur direkt lesbarer, sondern reduziert auch die Fehleranfälligkeit bei der Deklaration. Jede Funktion erfüllt exakt einen klaren Zweck, was dem Prinzip der strikten Aufgabentrennung sehr entgegenkommt.
Beide Layouts sind darauf ausgelegt, ihre Kinder linear anzuordnen, ohne sie automatisch in eine neue Zeile oder Spalte umzubrechen. Das bedeutet konkret: Wenn der kumulierte Inhalt einer Row breiter als die physikalische Bildschirmbreite ist, wird der überschüssige Inhalt abgeschnitten, sofern du kein explizites Scroll-Verhalten implementierst. Gleiches gilt für eine Column, deren Inhalt die verfügbare Bildschirmhöhe überschreitet. Sie bilden somit das unkomplizierte Fundament, auf dem komplexere Layout-Entscheidungen wie Grids, flexibel umbrechende Layouts oder speichereffiziente Listen aufbauen. Als Android-Entwickler wirst du bei der Strukturierung alltäglicher Bildschirme, wie einer Login-Maske, einer Navigationsleiste oder einer Listeneintrags-Karte, in der überwiegenden Zahl der Fälle mit exakt diesen beiden Primitiven deinen Aufbau beginnen.
Wie funktioniert es?
Das Verhalten von Rows und Columns wird maßgeblich durch zwei zentrale Konzepte gesteuert, die du zwingend unterscheiden und verinnerlichen musst: Arrangement und Alignment. Diese beiden Begriffe bereiten beim Einstieg oft Schwierigkeiten, folgen aber in Jetpack Compose einer streng logischen, geometrischen Regel.
Jedes lineare Layout hat eine Hauptachse (Main Axis) und eine Querachse (Cross Axis). Das Verständnis dieser Achsen ist der Schlüssel zur fehlerfreien Platzierung deiner Views.
Bei einer Row verläuft die Hauptachse horizontal (von links nach rechts in Standard-Layouts) und die Querachse verläuft vertikal (von oben nach unten).
Bei einer Column verläuft die Hauptachse vertikal (von oben nach unten) und die Querachse verläuft horizontal (von links nach rechts).
Arrangement (Anordnung auf der Hauptachse)
Mit dem Parameter horizontalArrangement bei einer Row oder verticalArrangement bei einer Column bestimmst du, wie der verfügbare, noch nicht genutzte Platz auf der Hauptachse zwischen den Kind-Elementen verteilt wird. Die Compose-API bietet hierfür vordefinierte Konstanten an. Ein Arrangement.Start (bei Rows) oder Arrangement.Top (bei Columns) packt alle Elemente lückenlos an den Anfang des Containers. Wenn du den Freiraum zwischen den Elementen aufteilen möchtest, nutzt du Optionen wie Arrangement.SpaceBetween (das erste Element klebt am Anfang, das letzte am Ende, der Rest wird dazwischen gleichmäßig verteilt) oder Arrangement.SpaceEvenly (identischer Abstand vor dem ersten, zwischen allen und nach dem letzten Element). Alternativ kannst du mit Arrangement.spacedBy(16.dp) einen exakt definierten, festen Abstand zwischen allen Elementen erzwingen, ohne den restlichen Freiraum zu beeinflussen.
Alignment (Ausrichtung auf der Querachse)
Der Parameter verticalAlignment bei einer Row beziehungsweise horizontalAlignment bei einer Column steuert die Positionierung der Elemente auf der jeweiligen Querachse. Angenommen, du hast eine Row, deren Container durch ein großes Icon deutlich höher ist als ein darin enthaltener Textblock. In diesem Fall kannst du mit Alignment.CenterVertically dafür sorgen, dass der Text auf der vertikalen Mittelachse der Row sauber zentriert wird. Bei einer Column, die unterschiedlich breite Buttons enthält, zentrierst du diese horizontal mit Alignment.CenterHorizontally.
Zusätzlich zur Positionierung auf der globalen Container-Ebene kannst du einzelnen, spezifischen Kind-Elementen eigene Modifier mitgeben. Der weight-Modifier nimmt hierbei eine Sonderstellung ein. Er weist einem bestimmten Element einen prozentualen, flexiblen Anteil des verbleibenden Platzes auf der Hauptachse zu. Jetpack Compose misst dabei zuerst alle unflexiblen Elemente und verteilt den Restraum anschließend anhand der deklarierten Gewichtungen der verbleibenden Elemente.
In der Praxis
In der täglichen Projektarbeit setzt du Rows und Columns permanent ein, um einzelne UI-Komponenten präzise zu strukturieren. Ein absolut typischer Anwendungsfall ist eine Profil-Karte für eine Kontaktliste, die links ein Avatar-Bild und rechts daneben vertikal angeordnet den Namen und den aktuellen Status des Nutzers anzeigt.
Hier ist ein praxisnahes Beispiel, das verdeutlicht, wie du Row und Column sinnvoll verschachtelst und mit den Parametern für Arrangement sowie Alignment steuerst, um eine robuste Komponente zu erzeugen:
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun UserProfileCard(name: String, status: String) {
// Die Row ordnet das Bild und die Text-Spalte horizontal an
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
// Platzhalter für ein Avatar-Bild, rund zugeschnitten
Box(
modifier = Modifier
.size(56.dp)
.clip(CircleShape)
.background(Color.LightGray)
)
// Die Column ordnet Name und Status vertikal an
// Der weight-Modifier sorgt dafür, dass die Texte den restlichen Platz einnehmen
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.Center
) {
Text(
text = name,
fontSize = 18.sp,
color = Color.Black
)
Text(
text = status,
fontSize = 14.sp,
color = Color.DarkGray
)
}
}
}
Nutze Row und Column exklusiv für eindimensionale, überschaubare Layouts mit einer festen Anzahl an Elementen. Sobald du evaluierst, dass Elemente auf der Hauptachse den Bildschirmrand überschreiten könnten und in die nächste Zeile umbrechen müssen, verwendest du stattdessen die speziellen APIs FlowRow oder FlowColumn. Wenn deine Liste an Elementen dynamisch wächst, aus einer Datenbank geladen wird und den sichtbaren Scrollbereich überschreiten kann, musst du aus Performance-Gründen zwingend auf LazyColumn oder LazyRow wechseln. Reguläre Rows und Columns instanziieren sofort alle Kind-Elemente und unterstützen kein Recycling der Views, was bei langen Listen unvermeidlich zu spürbaren Einbrüchen der Bildwiederholrate oder zu Speicherfehlern führt.
Ein Fehler, der in Code-Reviews immer wieder auffällt, ist das unbedachte Verschachteln von Elementen mit dem weight-Modifier innerhalb scrollbarer Layout-Container. Wenn du eine Column in einen verticalScroll-Modifier hüllst, ist ihre messbare Höhe theoretisch unendlich, da sie beliebig weit scrollen kann. Wendest du nun einen weight-Modifier auf ein Kind innerhalb dieser spezifischen Column an, führt dies zu einem Absturz zur Laufzeit oder zu einem massiven Darstellungsfehler. Jetpack Compose ist nicht in der Lage, den prozentualen Anteil einer mathematisch unendlichen Höhe zu berechnen. Achte bei der Entwicklung stets akribisch darauf, weight ausschließlich in Layouts mit fest definierten oder durch den Bildschirm limitierten Grenzen zu verwenden.
Fazit
Rows und Columns bilden die unverzichtbaren Grundpfeiler jedes Jetpack Compose Layouts. Durch das klare, architektonische Verständnis der strikten Trennung von Arrangement für die Verteilung auf der Hauptachse und Alignment für die Ausrichtung auf der Querachse bist du in der Lage, präzise, performante und vorhersehbare Benutzeroberflächen zu konstruieren. Um dieses Wissen praktisch zu festigen, solltest du das obige Code-Beispiel umgehend in dein eigenes Android-Projekt kopieren und intensiv im Layout Inspector von Android Studio untersuchen. Verändere testweise die Parameter für Arrangement und Alignment, aktiviere die visuelle Anzeige der Layout-Grenzen auf deinem physischen Testgerät oder im Emulator und beobachte exakt, wie Jetpack Compose den verfügbaren Bildschirmplatz bei jeder Modifikation neu berechnet und die einzelnen Komponenten verschiebt. Durch diese gezielte Überprüfung stellst du sicher, dass dein theoretisches Modell der Compose-Primitive vollumfänglich mit dem tatsächlichen Rendering-Verhalten der Engine übereinstimmt und du für komplexere Architekturaufgaben gewappnet bist.