
In this article, we’ll learn how to implement lazy grid layouts in Android Jetpack Compose.
Prerequisites:
What are Lazy Grid Layouts in Jetpack Compose?
Lazy grid layouts are used to display items in a grid. They only render the items that are currently visible on the screen. As a result, they are memory efficient for displaying a large set of data, such as images from a gallery.
For this article, create an empty Jetpack Compose project and open MainActivity.kt. Create a composable called MyUI() and call it from the onCreate().
// we need the following packages
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme(darkTheme = false) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier.fillMaxSize()
) {
MyUI()
}
}
}
}
}
}
@Composable
fun MyUI() {
}
We’ll write our code in the MyUI().
Jetpack Compose provides two lazy grid APIs:
1. Lazy Vertical Grid Example:
It displays a vertically scrolling grid. The API looks like this:
@Composable
fun LazyVerticalGrid(
columns: GridCells,
modifier: Modifier = Modifier,
state: LazyGridState = rememberLazyGridState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical =
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyGridScope.() -> Unit
)
columns – Number of columns of the grid. Instead of a number, we can also set the minimum size for each item.
modifier – The modifier to apply to this layout.
state – The state of the list.
contentPadding – It adds a margin around the whole content.
reverseLayout – Reverse the direction of scrolling and layout.
verticalArrangement – The vertical arrangement of the layout’s children.
horizontalArrangement – The horizontal arrangement of the layout’s children.
flingBehavior – Logic describing the fling behavior.
userScrollEnabled – Whether scrolling via the user gestures or accessibility actions is allowed. You can still scroll programmatically using the state even when it is disabled.
content – The content of the list. We add items (children) here.
The number of columns depends on the columns parameter. There are two options – Fixed and Adaptive.
Fixed Columns:
We use GridCells.Fixed() class to create a grid with fixed number of columns.
class Fixed(private val count: Int) : GridCells {}
The count parameter determines the number of columns. For example, if count = 5, there will be five columns. Each column will have a width of 1/5th of the parent’s width.
For example, if the parent’s width is 100 pixels, each column will have a width of 20 pixels. The columns will be evenly distributed.
Adaptive Columns:
We use GridCells.Adaptive() class to create a grid with adaptive size.
class Adaptive(private val minSize: Dp) : GridCells {}
It creates as many columns as possible with the condition that each column has at least minSize width. All the columns have equal width.
For example, if minSize = 20.dp, there will be as many columns as possible, and every column has a width of at least 20.dp. If the screen is 88.dp wide, there will be four columns with 22.dp each.
Simple Lazy Vertical Grid Example:
The columns and content parameters are mandatory.
@Composable
fun MyUI() {
LazyVerticalGrid(
modifier = Modifier.fillMaxSize(),
columns = GridCells.Fixed(count = 4)
) {
items(count = 100) { index ->
Box(
modifier = Modifier
.fillMaxWidth()
.height(height = 100.dp)
.background(color = Color.Magenta, shape = RoundedCornerShape(size = 4.dp)),
contentAlignment = Alignment.Center
) {
Text(
text = "$index",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
}
}
Output:

The output doesn’t look good because children don’t have a margin. Let’s add some margin to improve the appearance.
Margin/Padding Between Children:
There are three parameters to add padding – verticalArrangement, horizontalArrangement, and contentPadding.
verticalArrangement – Adds top and bottom margin between each item.
horizontalArrangement – Adds left and right margin between each item.
contentPadding – Adds margin to the whole layout.
@Composable
fun MyUI() {
LazyVerticalGrid(
modifier = Modifier.fillMaxSize(),
columns = GridCells.Fixed(count = 4),
verticalArrangement = Arrangement.spacedBy(space = 16.dp), // top and bottom margin between each item
horizontalArrangement = Arrangement.spacedBy(space = 16.dp), // left and right margin between each item
contentPadding = PaddingValues(all = 10.dp) // margin for the whole layout
) {
items(count = 100) { index ->
Box(
modifier = Modifier
.fillMaxWidth()
.height(height = 100.dp)
.background(color = Color.Magenta, shape = RoundedCornerShape(size = 4.dp)),
contentAlignment = Alignment.Center
) {
Text(
text = "$index",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
}
}
Output:

Lazy Vertical Grid Adaptive Size:
Instead of a fixed size, let’s create a grid with an adaptive number of columns.
@Composable
fun MyUI() {
LazyVerticalGrid(
modifier = Modifier.fillMaxSize(),
columns = GridCells.Adaptive(minSize = 100.dp), // adaptive size
verticalArrangement = Arrangement.spacedBy(space = 16.dp),
horizontalArrangement = Arrangement.spacedBy(space = 16.dp),
contentPadding = PaddingValues(all = 10.dp)
) {
items(count = 100) { index ->
Box(
modifier = Modifier
.fillMaxWidth()
.height(height = 100.dp)
.background(color = Color.Magenta, shape = RoundedCornerShape(size = 4.dp)),
contentAlignment = Alignment.Center
) {
Text(
text = "$index",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
}
}
Output:

2. Lazy Horizontal Grid:
It creates a horizontally scrollable list.
fun LazyHorizontalGrid(
rows: GridCells,
modifier: Modifier = Modifier,
state: LazyGridState = rememberLazyGridState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
horizontalArrangement: Arrangement.Horizontal =
if (!reverseLayout) Arrangement.Start else Arrangement.End,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyGridScope.() -> Unit
)
The parameters are similar to LazyVerticalGrid.
Simple Lazy Horizontal Grid Example:
The rows and content parameters are mandatory.
@Composable
fun MyUI() {
LazyHorizontalGrid(
modifier = Modifier.fillMaxSize(),
rows = GridCells.Fixed(count = 4),
verticalArrangement = Arrangement.spacedBy(space = 16.dp), // top and bottom margin for each item
horizontalArrangement = Arrangement.spacedBy(space = 16.dp), // left and right margin for each item
contentPadding = PaddingValues(all = 10.dp) // margin for the whole layout
) {
items(count = 100) { index ->
Box(
modifier = Modifier
.fillMaxHeight()
.width(width = 100.dp)
.background(color = Color.Magenta, shape = RoundedCornerShape(size = 4.dp)),
contentAlignment = Alignment.Center
) {
Text(
text = "$index",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
}
}
Output:

Adaptive Size:
To set the adaptive size, use the same GridCells.Adaptive() method.
@Composable
fun MyUI() {
LazyHorizontalGrid(
modifier = Modifier.fillMaxSize(),
rows = GridCells.Adaptive(minSize = 80.dp), // adaptive size
verticalArrangement = Arrangement.spacedBy(space = 16.dp),
horizontalArrangement = Arrangement.spacedBy(space = 16.dp),
contentPadding = PaddingValues(all = 10.dp)
) {
items(count = 100) { index ->
Box(
modifier = Modifier
.fillMaxHeight()
.width(width = 100.dp)
.background(color = Color.Magenta, shape = RoundedCornerShape(size = 4.dp)),
contentAlignment = Alignment.Center
) {
Text(
text = "$index",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
}
}
Output:

This is all about lazy grid layouts in Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.
Related Posts:
- Material 3 TopAppBar in Jetpack Compose (with Examples)
- How to Paste Code into MS Word with Formatting?
- 3 Ways to Create Lines in Jetpack Compose
- How to Get App Install and Uninstall Events in Android?
References: