Jetpack Compose Layout Fundamentals: Column, Row, Box Explained
Jetpack Compose has revolutionized Android UI development by introducing a declarative approach to building user interfaces. At the heart of this modern framework lie three fundamental layout composables: Column, Row, and Box. Understanding these building blocks is essential for anyone looking to master Compose and create beautiful, responsive Android applications.
Introduction to Compose Layouts
Unlike traditional XML-based layouts in Android, Jetpack Compose uses composable functions to define UI structure. This functional approach brings several advantages: better code reusability, improved testability, and a more intuitive way to express complex layouts.
The three primary layout composables—Column, Row, and Box—form the foundation of almost every Compose UI. They provide different ways to arrange and organize child composables, each serving specific layout purposes.
Column: Arranging Elements Vertically
What is Column?
Column is a composable that arranges its child elements vertically, stacking them on top of each other from top to bottom. It's the Compose equivalent of LinearLayout with vertical orientation in traditional Android development.
Basic Column Example
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun SimpleColumn() {
Column {
Text("First Item")
Text("Second Item")
Text("Third Item")
}
}
In this example, three Text composables are arranged vertically in the order they appear in the code.
Column with Modifiers
Modifiers are a powerful Compose feature that allow you to decorate or augment a composable. Common modifiers for Column include padding, fillMaxWidth, and size.
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun PaddedColumn() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text("Item with padding")
Text("Another item")
}
}
Here, fillMaxWidth() makes the Column occupy the full width of its parent, while padding(16.dp) adds 16 density-independent pixels of space around all sides.
Column Arrangement and Alignment
You can control how child elements are distributed vertically using the verticalArrangement parameter and how they align horizontally using horizontalAlignment.
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Alignment
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ArrangedColumn() {
Column(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Top")
Text("Middle")
Text("Bottom")
}
}
In this example, Arrangement.SpaceEvenly distributes items with equal space between them, and Alignment.CenterHorizontally centers each item horizontally.
Row: Arranging Elements Horizontally
What is Row?
Row is the horizontal counterpart to Column. It arranges child elements from left to right in a single row, equivalent to LinearLayout with horizontal orientation in traditional Android.
Basic Row Example
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun SimpleRow() {
Row {
Text("First")
Text("Second")
Text("Third")
}
}
Row with Weight
The weight modifier is particularly useful in Row composables for distributing available space proportionally among children.
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.weight
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun WeightedRow() {
Row(modifier = Modifier.fillMaxWidth()) {
Text("Item 1", modifier = Modifier.weight(1f))
Text("Item 2", modifier = Modifier.weight(2f))
Text("Item 3", modifier = Modifier.weight(1f))
}
}
In this example, "Item 2" will occupy twice as much horizontal space as "Item 1" and "Item 3" because its weight is 2f.
Row Arrangement and Alignment
Similar to Column, Row supports horizontalArrangement and verticalAlignment parameters.
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Alignment
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ArrangedRow() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text("Left")
Text("Right")
}
}
Box: Overlaying and Stacking Elements
What is Box?
Box is a layout composable that allows you to layer child elements on top of each other, similar to a FrameLayout in traditional Android development. Unlike Column and Row, Box stacks its children in the order they appear, with later children rendered on top of earlier ones.
Basic Box Example
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun SimpleBox() {
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Blue)
) {
Text("Text on blue background")
}
}
Box with Content Alignment
You can align content within a Box using the contentAlignment parameter.
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Alignment
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun CenteredBox() {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
Text("Centered Content")
}
}
Modifier Fundamentals
Modifiers are chainable and immutable objects that describe how a composable should look and behave. Here are common modifiers:
Padding and Size
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun ModifierExamples() {
Text(
"Padded and sized",
modifier = Modifier
.padding(8.dp)
.width(100.dp)
.height(50.dp)
)
}
Fill Modifiers
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun FillModifiers() {
Column(modifier = Modifier.fillMaxSize()) {
Text("Full width", modifier = Modifier.fillMaxWidth())
Text("Full height", modifier = Modifier.fillMaxHeight())
}
}
Spacer: Adding Space Between Elements
Spacer is a simple composable that takes up space without rendering anything visible. It's useful for creating gaps between elements.
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun SpacerExample() {
Column {
Text("First item")
Spacer(modifier = Modifier.height(16.dp))
Text("Second item with gap above")
}
}
Using Scaffold for Structured Layouts
Scaffold provides a pre-built layout structure that includes a top app bar, bottom navigation, floating action button, and content area. It's ideal for creating standard Material Design layouts.
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ScaffoldExample() {
Scaffold(
topBar = {
TopAppBar(title = { Text("My App") })
}
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
Text("Content goes here")
}
}
}
Using Surface for Visual Depth
Surface is a composable that applies Material Design elevation and styling to its content. It's commonly used to create cards and containers.
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun SurfaceCard() {
Surface(
color = Color.White,
modifier = Modifier.padding(16.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text("Card Title")
Text("Card content goes here")
}
}
}
Combining Layouts: A Practical Example
Here's a complete example that combines Column, Row, Box, and various modifiers to create a user profile card:
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun UserProfileCard() {
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("John Doe", fontSize = 18.sp, fontWeight = FontWeight.Bold)
Box(
modifier = Modifier
.size(24.dp)
.background(Color.Blue)
)
}
Text("Android Developer", fontSize = 14.sp, color = Color.Gray)
Spacer(modifier = Modifier.height(8.dp))
Text("Passionate about Compose and modern Android development.")
}
}
}
Best Practices
- Use Modifiers Efficiently: Chain modifiers in logical order for better readability and performance.
- Leverage verticalArrangement and Alignment: These powerful parameters reduce the need for complex nested layouts.
- Spacer for Precise Control: Use Spacer when you need exact spacing instead of relying solely on Arrangement.
- Prefer Column/Row over Nested Boxes: These specialized layouts are more performant than Box for linear arrangements.
- Use Scaffold for Standard Layouts: Don't reinvent the wheel—Scaffold handles common Material Design patterns.
Conclusion
Mastering Column, Row, and Box is fundamental to becoming proficient with Jetpack Compose. These three layout composables, combined with modifiers and alignment parameters, provide all the tools you need to create complex, responsive Android UIs. With practice, you'll find that declarative layout composition becomes intuitive and enjoyable.
The key is to think in terms of composable functions and layout hierarchy rather than XML resources. Start simple, experiment with modifiers and arrangement parameters, and gradually build more complex layouts.
All 8 templates use clean Compose layouts. https://myougatheax.gumroad.com
Top comments (0)