Layouts in Jetpack Compose


Introduction
Jetpack Compose is a new way to build user interfaces (UIs) for Android apps. Instead of writing layout code in XML (which looks like HTML), developers can now create designs directly using Kotlin, a programming language. This makes the code shorter, easier to read, and more flexible.
In this blog, we’ll look at how layouts work in Jetpack Compose and explain the basic ideas that make it a powerful tool for building Android app screens.
What are layouts?
In an Android app, layouts define how UI elements are arranged and displayed on the screen. They provide the structure and organization for components like buttons, text views, images, etc., determining their position, size, alignment, and behavior.
Purpose of Layout:
Define the visual structure of the app's screen or UI component.
Handle responsive design by adjusting to different screen sizes, orientations, and densities.
Organize components horizontally, vertically, in grids, or in overlapping layers.
Layouts in Jetpack Compose vs XML
Parameter | Jetpack Compose | XML |
Approach | Declarative UI – describe what the UI should look like for a given state | Imperative – define static structure and manipulate UI via code |
Language | Pure Kotlin (UI + logic in one place) | UI in XML, logic in Kotlin/Java |
Dynamic UI Handling | Supports conditionals, loops, and state directly in layouts | Requires view visibility toggling and manual updates |
Performance | Efficient recomposition, no view inflation | View inflation adds overhead; nested views impact performance |
Custom Layouts and Reusability | Easy to create reusable composable functions | Requires custom View/ViewGroup classes |
Tooling and Previews | Live Previews, Interactive Previews, Preview Parameters | Traditional Layout Editor with drag-and-drop |
State Menagement | Integrated with remember and mutableStateOf | Managed externally through findViewById, LiveData, etc. |
Modularity | Composable functions promote modular, testable UIs | Reusability through include or fragments is less flexible |
Types of Layouts (Traditional XML)
LinearLayout – Arranges children in a single row or column.
RelativeLayout – Positions children relative to each other or the parent.
ConstraintLayout – A powerful and flexible layout system using constraints.
FrameLayout – Stacks views on top of each other.
GridLayout – Places items in a grid-like structure.
Types of Layouts (Jetpack Compose)
Column – vertical arrangement
Row – horizontal arrangement
Box – layered stacking
Lazy Row/Column – efficient scrolling list
Without any Layout
In an Android app, layouts are essential for defining the structure and positioning of UI elements. Without a layout, the app's user interface cannot be properly rendered or organized.
In Jetpack Compose, the rules are more flexible due to its declarative nature. Technically, you can write composables like Text("Hello") or Button(...) without wrapping them in a layout composable such as Column, Row, or Box. Compose will still compile and run, but the resulting UI might not behave as expected. Without a layout, multiple elements may stack on top of each other, appear misaligned, or overflow their bounds. You lose control over alignment, spacing, and screen responsiveness, which can lead to a broken or visually inconsistent UI.
Example:
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnNoLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnNoLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
Text(text = "Hello Column", modifier = Modifier.padding(innerPadding))
Text(text = "Hello Row", modifier = Modifier.padding(innerPadding))
Text(text = "Hello Box", modifier = Modifier.padding(innerPadding))
}
Explanation:
The MainActivity class is the entry point of this Android application. It extends ComponentActivity, which is a part of Jetpack Compose's integration with Android components. Inside the onCreate method, enableEdgeToEdge() is called to allow the app content to draw behind system bars like the status bar or navigation bar, giving a more immersive look. The setContent block is used to define the user interface of the activity using Jetpack Compose. Within this block, the BasicsJCTheme is applied to ensure consistent styling across the app based on your custom theme. The Scaffold composable is used as a base layout structure, commonly used to provide basic app structure elements like top bars, floating action buttons, and padding. Here, it wraps the main content and passes the appropriate padding (innerPadding) to ensure that content is not obscured by system UI or app bars.
The LearnNoLayout composable function attempts to display three separate Text elements, each with a greeting message like "Hello Column", "Hello Row", and "Hello Box". Each Text is wrapped in a Modifier.padding(innerPadding), which ensures that the text content doesn't clash with system UI elements like the status bar or navigation bar, assuming it's used inside a Scaffold.
However, there's an important concept to understand here: in Jetpack Compose, composables must be wrapped inside a layout container like Column, Row, or Box if you want to display multiple elements properly. In this case, since the three Text elements are not wrapped inside any layout, only the first one ("Hello Column") will be visible, and the others will be ignored. This is because composables, by default, don’t stack unless explicitly told to do so.
Column Layout
In Jetpack Compose, a Column is a layout composable that places its children in a vertical sequence. It’s similar to a LinearLayout with vertical orientation in XML-based Android views.
When you place composables inside a Column, they are rendered in the order they are written, stacking from top to bottom.
Using Column is straightforward. It accepts parameters such as modifier, verticalArrangement, and horizontalAlignment to control spacing and alignment. For example, you can align children to the center horizontally or add vertical spacing between items. It is particularly useful when building forms, lists, or any vertically structured UI.
Example
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnColumnLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnColumnLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
Column(modifier = Modifier.padding(innerPadding)
.fillMaxSize()
.background(Color.Yellow),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,) {
Text(text = "Hello Item 1")
Text(text = "Hello Item 2")
Text(text = "Hello item 3")
}
}
Explanation:
The LearnColumnLayout composable function defines the actual content displayed on the screen. It uses a Column layout, which arranges its child elements vertically, one below the other. The Modifier applied to the Column ensures it fills the entire screen (fillMaxSize()), applies padding from the scaffold (padding(innerPadding)), and sets the background color to yellow (background(Color.Yellow)). The horizontalAlignment = Alignment.CenterHorizontally centers all child elements horizontally within the column, while verticalArrangement = Arrangement.Center places the child elements in the center of the column vertically. Inside the column, three Text composables are used to display simple greeting messages ("Hello Item 1", "Hello Item 2", and "Hello item 3"), stacked one below the other and centered on the screen.
Key Parameters
modifier: Used to apply layout and styling modifiers (like padding, size, etc.)
verticalArrangement: Controls the vertical spacing and arrangement of children. Options include:
Arrangement.Top
Arrangement.Center
Arrangement.Bottom
Arrangement.SpaceBetween,
Arrangement.SpaceAround,
Arrangement.SpaceEvenly
horizontalAlignment: Aligns children horizontally within the column. Options include:
Alignment.Start
Alignment.CenterHorizontally
Alignment.End
Use When
You want to place items vertically — one below the other
Use Case:
Login/Signup Screen
User Profile Info
Settings Page
Form Page
Row Layout
The Row layout in Jetpack Compose arranges its children horizontally, from left to right. It is analogous to LinearLayout with a horizontal orientation in XML, but Compose makes it significantly more intuitive and flexible to use. Row is ideal when you want to place UI elements side by side—such as buttons, icons with text, or evenly spaced columns of data.
Like Column, the Row composable accepts optional parameters such as modifier, horizontalArrangement, and verticalAlignment to control spacing and alignment within the row. This allows for precise positioning and alignment of content along both axes. For example, you can space items evenly across the width or align them to the center vertically.
Example
Code:
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnRowLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnRowLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
Row (modifier = Modifier.padding(innerPadding)
.fillMaxSize()
.background(Color.Yellow),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center) {
Text(text = "Hello Item 1")
Text(text = "Hello Item 2")
Text(text = "Hello item 3")
}
}
Explanation:
The LearnRowLayout function is a composable that contains the actual content to display on the screen. Instead of stacking items vertically, it uses a Row layout, which arranges its children side by side in a horizontal line. The Modifier applied to the row ensures three things: it fills the entire screen (fillMaxSize()), respects the padding provided by the scaffold (padding(innerPadding)), and sets the background color of the entire row to yellow (background(Color.Yellow)). The verticalAlignment = Alignment.CenterVertically centers all the child elements vertically within the row, while horizontalArrangement = Arrangement.Center ensures that the items are placed together in the center of the screen horizontally. Inside the row, three Text elements are displayed, each showing a greeting message ("Hello Item 1", "Hello Item 2", and "Hello item 3"). These texts appear next to each other, aligned in the center of the screen.
Key Parameters
modifier: Applies styling (like size, padding, background, etc.)
horizontalArrangement: Manages horizontal spacing between children. Options include:
Arrangement.Start, End, Center
Arrangement.SpaceBetween, SpaceAround, SpaceEvenly
verticalAlignment: Aligns children vertically within the row.
Alignment.Top
Alignment.CenterVertically
Alignment.Bottom
Use When
You want to place items horizontally — side by side
Use Case:
Top App Bar
Price and Rating Display
Two-column Form (First name and last name)
Buttons Row (Cancel and save buttons)
Box Layout
The Box layout in Jetpack Compose allows you to stack composables on top of each other, similar to how a FrameLayout works in traditional XML layouts. It’s especially useful when you want to overlay elements, create background layers, or position items relative to the container’s bounds. With Box, the first child is drawn first (i.e., at the bottom), and subsequent children are rendered on top in the order they appear.
One of the key features of Box is its support for alignment modifiers, such as Modifier.align(), which let you position each child individually within the box. You can align elements to the top-start, center, bottom-end, or anywhere within the container. Additionally, you can use Modifier.fillMaxSize() or fixed dimensions to control the overall size of the box.
Example
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnBoxLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnBoxLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
Box(modifier = Modifier.padding(innerPadding)
.fillMaxSize()
.background(Color.Yellow),
contentAlignment = Alignment.Center){
Box(modifier = Modifier.height(300.dp)
.width(300.dp)
.background(Color.Blue)) {
Text(text = "Hello Box",
modifier = Modifier.align(Alignment.Center),
Color.White,
fontSize = 30.sp)
}
}
}
Explanation:
The LearnBoxLayout function is a composable—a building block in Jetpack Compose that defines part of the UI. This particular composable uses the Box layout, which is similar to a frame: it allows you to stack child elements on top of each other and control their alignment. The outer Box fills the entire screen (fillMaxSize()), respects the padding provided by the Scaffold layout (padding(innerPadding)), and has a yellow background (background(Color.Yellow)). The contentAlignment = Alignment.Center property ensures that any content placed inside this outer box will be centered both vertically and horizontally.
Inside this outer box, there's another smaller Box, which is 300dp wide and 300dp tall and has a blue background. This inner box serves as a container to center and highlight the text. Within it, a Text composable is used to display the message "Hello Box". The Modifier.align(Alignment.Center) ensures the text is placed in the exact center of the blue box. The text color is set to white (Color.White), and the font size is set to 30sp, making it prominent and easy to read.
Key Parameters
modifier: For applying size, padding, background, etc.
contentAlignment: Aligns all children by default inside the Box (e.g., Alignment.TopStart, Center, BottomEnd, etc.)
Use When
You want to stack elements on top of each other or overlay content.
Use Case:
Image and Text overlay
Notification Badge on Icon
Floating action button over content
Loading indicator overlay
Lazy Row
LazyRow is a powerful composable in Jetpack Compose used to display a horizontally scrolling list of items. It is part of the Lazy layout family, which includes LazyColumn and LazyVerticalGrid, and is designed for performance and efficiency by composing only the visible items on screen. This makes it ideal for building horizontally scrollable carousels, image sliders, or category lists where content may be large or dynamic.
Unlike a regular Row, which renders all its children eagerly, LazyRow is optimized for large or dynamic data sets and supports item recycling under the hood. It provides APIs such as items() and itemsIndexed() to generate content from a list or collection, and supports modifiers for padding, spacing, and alignment.
Example
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.lazy.items
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnLazyRowLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnLazyRowLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
val itemList = listOf("Hello Item 1", "Hello Item 2", "Hello Item 3", "Hello Item 4", "Hello Item 5"
, "Hello Item 6", "Hello Item 7", "Hello Item 8", "Hello Item 9", "Hello Item 10"
, "Hello Item 11", "Hello Item 12", "Hello Item 13", "Hello Item 14", "Hello Item 15")
LazyRow (
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.background(Color.Yellow),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp) // spacing between items
) {
items(itemList) { item ->
Text(text = item)
}
}
}
Explanation:
The LearnLazyRowLayout composable is designed to display a horizontally scrollable list of text items using a layout called LazyRow. First, a list of string items named itemList is created. Each item in this list contains a greeting message like "Hello Item 1", "Hello Item 2", and so on up to "Hello Item 15".
The LazyRow composable is then used to display these items in a single horizontal line that can scroll sideways if there are more items than can fit on the screen. This is especially useful when showing a large number of items efficiently, as it only renders what is visible on screen — which is why it's called "lazy."
The Modifier applied to the LazyRow does a few things: it applies the padding from the Scaffold (padding(innerPadding)), makes the row fill the entire screen (fillMaxSize()), and sets the background color to yellow (background(Color.Yellow)). The verticalAlignment = Alignment.CenterVertically ensures that all items are vertically centered within the row. The horizontalArrangement = Arrangement.spacedBy(16.dp) adds 16dp of horizontal space between each item to make the layout look cleaner and more spaced out.
Finally, the items(itemList) block is what creates each item in the row. For every string in itemList, a Text composable is created to display that string on the screen.
Use When
You need a horizontally scrollable list
Use Case:
You're creating UI components like:
Image carousels
Category selectors
Horizontal product sliders (e.g., in e-commerce apps)
Chip filters or story lists (like Instagram stories)
You want horizontal content to scroll efficiently with lazy composition.
You’re building nested scrollable layouts (e.g., a LazyColumn with multiple LazyRows).
Lazy Column
LazyColumn is a key layout in Jetpack Compose used to display a vertically scrolling list of items efficiently. It is the Compose equivalent of RecyclerView in the traditional Android View system but is much simpler to implement and more flexible. As a member of the Lazy layout family, LazyColumn only composes the visible items on screen, which enhances performance by avoiding unnecessary rendering of off-screen elements.
This composable is perfect for lists of any size—such as feeds, messages, or settings screens—and supports dynamic content rendering using functions like items(), itemsIndexed(), or item() for individual elements. It also provides parameters for spacing, padding, and alignment, making it highly customizable.
Example
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.lazy.items
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
LearnLazyColumnLayout(innerPadding)
}
}
}
}
}
@Composable
fun LearnLazyColumnLayout(innerPadding: androidx.compose.foundation.layout.PaddingValues) {
val itemList = listOf("Hello Item 1", "Hello Item 2", "Hello Item 3", "Hello Item 4", "Hello Item 5"
, "Hello Item 6", "Hello Item 7", "Hello Item 8", "Hello Item 9", "Hello Item 10"
, "Hello Item 11", "Hello Item 12", "Hello Item 13", "Hello Item 14", "Hello Item 15"
, "Hello Item 16", "Hello Item 17", "Hello Item 18", "Hello Item 19", "Hello Item 20")
LazyColumn (
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.background(Color.Yellow),
verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
items(itemList) { item ->
Text(text = item)
}
}
}
Explanation:
The LearnLazyColumnLayout composable function creates a vertically scrollable list using Jetpack Compose's LazyColumn. At the beginning, a list named itemList is defined containing 20 strings labeled "Hello Item 1" through "Hello Item 20". These are the items that will be displayed one below the other on the screen.
The LazyColumn layout is specifically designed for efficiently displaying long vertical lists. It only renders the items that are visible on the screen, making it more performance-friendly compared to a regular Column, especially when dealing with many items. The modifier applied to LazyColumn ensures that it fills the available space on the screen (fillMaxSize()), respects any padding from the parent layout (padding(innerPadding)), and uses a yellow background for the entire list area (background(Color.Yellow)).
Within the LazyColumn, the verticalArrangement = Arrangement.spacedBy(16.dp) adds 16dp of vertical space between each item, which improves readability and visual appeal. The horizontalAlignment = Alignment.CenterHorizontally centers each item horizontally within the column. Inside the items(itemList) block, each string from the list is displayed using a simple Text composable. As a result, all the greeting messages are shown in a neat, vertically scrollable list that is centered and evenly spaced.
Use When
You need a vertically scrollable list
Use Case:
You're building standard list-based UIs like:
Chat/message screens
News feeds
Settings or forms
Infinite scroll (e.g., social media timelines)
You want to display a large number of items efficiently, with only visible items composed.
You need to support scrolling gestures in the vertical direction.
After Words
Jetpack Compose has significantly changed the way we approach UI design in Android development. With its modern, declarative syntax and powerful layout system, developers now have more flexibility and control over how UI components are arranged on the screen. Throughout this blog, we've explored a variety of layout options — from the basic Column, Row, and Box, to more advanced and performance-optimized components like LazyRow and LazyColumn.
We also compared these Compose layouts with their traditional XML counterparts, understanding not only the structural differences but also the benefits that Compose brings in terms of readability, reusability, and responsiveness. We even saw what happens when we don’t use any layout at all — a subtle reminder of how important proper layout structure is in Compose.
Whether you're just starting out or transitioning from XML to Compose, grasping the layout system is a foundational step. Once you’re comfortable with these basics, you’ll find that building dynamic and interactive user interfaces becomes not just easier, but also more intuitive and fun.
As you continue your journey with Jetpack Compose, remember that layouts are just the beginning — there's a whole world of composable UI elements, animations, gestures, and state management waiting to be explored.
Happy Composing! ✨
Subscribe to my newsletter
Read articles from Jyoti Maurya directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jyoti Maurya
Jyoti Maurya
I create cross platform mobile apps with AI functionalities. Currently a PhD Scholar at Indira Gandhi Delhi Technical University for Women, Delhi. M.Tech in Artificial Intelligence (AI).