Open In App

Lazy Composables in Android Jetpack Compose – Columns, Rows, Grids

Last Updated : 28 Jul, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

In Jetpack compose we have Composables like Column and Row but when the app needs to display a large number of items in a row or columns then it’s not efficient if done by Row or Column Composable. Therefore we have Lazy Composables in Jetpack Compose. Mainly we have three kinds of Lazy Composables Row, Column, and Grid. In this article, we are going to look at all three Lazy Composables. We will build a simple app that demonstrates all three composables in action.

Prerequisites:

Step by Step Implementation

Step 1: Create a New Project (Or use it in the existing Compose project)

To create a new project in the Android Studio Canary version, refer to the article How to Create a new Project in the Android Studio Canary Version with Jetpack Compose.

Step 2 : Add Color (optional)

Open ui > theme > Colors.kt and add 

val GreenGfg = Color(0xFF0F9D58)

Step 3: Create Row and Column Items that are going to be displayed

Open MainActivity.kt and create two Composables, one for Row Item and One for Column Item

Kotlin




// Row Item with item Number 
@Composable
fun RowItem(number: Int) {
  
    // Simple Row Composable
    Row(
        modifier = Modifier
            .size(100.dp) // Size 100 dp
            .background(Color.White) // Background White
            .border(1.dp, GreenGfg), // Border color green
  
        // Align Items in Center
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
  
    ) {
        // Text Composable which displays some 
        // kind of message , text color is green
        Text(text = "This Is Item Number $number", color = GreenGfg)
    }
}
  
// Similar to row composable created above
@Composable
fun ColumnItem(number: Int) {
  
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .height(30.dp)
            .background(Color.White)
            .border(1.dp, GreenGfg),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
  
    ) {
        Text(text = "This Is Item Number $number", color = GreenGfg)
    }
}


Step 4: Working with Lazy Composables

Unline Column or Row Composable we cannot place composable inside directly inside Lazy Composables. Lazy Composables provides functions to place items in the LazyScope. There is mainly five overloaded functions. 

Function

Parameter

Functionality

item Composable Places one item in the LazyScope
items count,key(optional),Composable Places count items in the LazyScope
items List, Composable Places number of items present same as the size of List,
items Array, Composable Places number of items present same as the size of Array,
itemsIndexed Array/List,Composable

Places number of items present same as the size of Array,

and provides item(in list) and index of current Item.

Step 4.1: Lazy Row

Create a Composable in MainActivity.kt, here we will place Lazy row to demonstrate Lazy Row

Kotlin




@Composable
fun LazyRowExample(numbers: Array<Int>) {
  
    // Place A lazy Row
    LazyRow(
        contentPadding = PaddingValues(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
  
        // item places one item on the LazyScope
        item {
            RowItem(number = 0)
        }
  
        // items(count) places number of items supplied
        // as count and gives current count in the lazyItemScope
        items(10) {currentCount->
            RowItem(number = currentCount)
        }
  
        // items(list/array) places number of items same as
        // the size of list/array and gives current list/array
        // item in the lazyItemScope
        items(numbers) {arrayItem-> // Here numbers is Array<Int> so we 
                                      // get Int in the scope.
            RowItem(number = arrayItem)
        }
  
        // items(list/array) places number of items same 
        // as the size of list/array and gives current list/array 
        // item and currentIndex in the lazyItemScope
        itemsIndexed(numbers) { index: Int, item: Int ->
            RowItem(number = index)
        }
    }
}


 Step 4.2: Lazy Column

Create a Composable in MainActivity.kt, here we will place Lazy Column to demonstrate Lazy Column

Kotlin




@Composable
fun ColumnExample(numbers: Array<Int>) {
  
    LazyColumn(
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // item places one item on the LazyScope
        item {
            ColumnItem(number = 0)
        }
  
        // items(count) places number of items supplied 
        // as count and gives current count in the lazyItemScope
        items(10) {currentCount->
            ColumnItem(number = currentCount)
        }
  
        // items(list/array) places number of items same
        // as the size of list/array and gives current 
        // list/array item in the lazyItemScope
        items(numbers) {arrayItem->
            ColumnItem(number = arrayItem)
        }
  
        // items(list/array) places number of items 
        // same as the size of list/array and gives
        // current list/array item and currentIndex 
        // in the lazyItemScope
        itemsIndexed(numbers) { index, item ->
            ColumnItem(number = index)
        }
    }
}


Step 4.3: Lazy Grid

Create a Composable in MainActivity.kt, here we will place LazyVerticalGrid. It’s almost the same as other lazy composable but it takes an extra parameter cells which is the number of grid items in one row / minimum width of one item. cells can be either GridCells.Fixed(count), It fixes the items displayed in one grid row. Another value it accepts is GridCells.Adaptive(minWidth), it sets the minWidth of each grid item.

Kotlin




// add the annotation, 
// since [LazyVerticalGrid] is Experimental Api
@ExperimentalFoundationApi
@Composable
fun GridExample(numbers: Array<Int>) {
    // Lazy Vertical grid
    LazyVerticalGrid(
        // fix the item in one row to be 2.
        cells = GridCells.Fixed(2),
  
        contentPadding = PaddingValues(8.dp),
  
        ) {
        item {
            RowItem(number = 0)
        }
        items(10) {
            RowItem(number = it)
        }
        items(numbers) {
            RowItem(number = it)
        }
        itemsIndexed(numbers) { index, item ->
            RowItem(number = index)
        }
    }
}


Step 5: Placing the Composables on Screen

Now place all three examples in setContentView in MainActivity Class.

Kotlin




class MainActivity : ComponentActivity() {
  
    // Creates array as [0,1,2,3,4,5,.....99]
    private val numbers: Array<Int> = Array(100) { it + 1 }
  
    @ExperimentalFoundationApi
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LazyComponentsTheme {
  
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(Color.White)
                ) {
                    // Place the row and column 
                    // to take 50% height of screen
                    Column(Modifier.fillMaxHeight(0.5f)) {
                          
                        // Heading
                        Text(
                            text = "Row",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                          
                        // Lazy Row, pass the numbers array
                        LazyRowExample(numbers = numbers)
                          
                        // Heading
                        Text(
                            text = "Column",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                        // Lazy Column, Pass the numbers array
                        LazyColumnExample(numbers = numbers)
                    }
                      
                    Column(Modifier.fillMaxHeight()) {
                          
                        // Heading
                        Text(
                            text = "Grid",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                          
                        // Lazy Grid
                        GridExample(numbers = numbers)
                    }
                }
            }
        }
    }
}


Complete Code: 

Note: Before running this whole code, make sure to do Step 2, or replace GreenGfg with your own color.

Kotlin




import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.gfg.lazycomponents.ui.theme.GreenGfg
import com.gfg.lazycomponents.ui.theme.LazyComponentsTheme
  
class MainActivity : ComponentActivity() {
  
    // Creates array as [0,1,2,3,4,5,.....99]
    private val numbers: Array<Int> = Array(100) { it + 1 }
  
    @ExperimentalFoundationApi
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LazyComponentsTheme {
  
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(Color.White)
                ) {
                    // Place the row and column
                    // to take 50% height of screen
                    Column(Modifier.fillMaxHeight(0.5f)) {
  
                        // Heading
                        Text(
                            text = "Row",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
  
                        // Lazy Row,pass the numbers array
                        LazyRowExample(numbers = numbers)
  
                        // Heading
                        Text(
                            text = "Column",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                        // Lazy Column, Pass the numbers array
                        LazyColumnExample(numbers = numbers)
                    }
  
                    Column(Modifier.fillMaxHeight()) {
  
                        // Heading
                        Text(
                            text = "Grid",
                            color = Color.Black,
                            modifier = Modifier.padding(start = 8.dp)
                        )
  
                        // Lazy Grid
                        GridExample(numbers = numbers)
                    }
                }
            }
        }
    }
}
  
  
@Composable
fun LazyRowExample(numbers: Array<Int>) {
    // Place A lazy Row
    LazyRow(
        contentPadding = PaddingValues(8.dp),
          
        // Each Item in LazyRow have a 8.dp margin
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
  
        // item places one item on the LazyScope
        item {
            RowItem(number = 0)
        }
  
        // items(count) places number of items supplied
        // as count and gives current count in the lazyItemScope
        items(10) {currentCount->
            RowItem(number = currentCount)
        }
  
        // items(list/array) places number of items 
        // same as the size of list/array and gives 
        // current list/array item in the lazyItemScope
        items(numbers) {arrayItem-> // Here numbers is Array<Int> so we 
                                      // get Int in the scope.
            RowItem(number = arrayItem)
        }
  
        // items(list/array) places number of items 
        // same as the size of list/array and gives
        // current list/array item and currentIndex
        // in the lazyItemScope
        itemsIndexed(numbers) { index: Int, item: Int ->
            RowItem(number = index)
        }
    }
}
  
  
@Composable
fun RowItem(number: Int) {
    // Simple Row Composable
    Row(
        modifier = Modifier
            .size(100.dp) // Size 100 dp
            .background(Color.White) // Background White
            .border(1.dp, GreenGfg), // Border color green
  
        // Align Items in Center
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
    ) {
        // Text Composable which displays some 
        // kind of message , text color is green
        Text(text = "This Is Item Number $number", color = GreenGfg)
    }
}
  
@Composable
fun ColumnItem(number: Int) {
  
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .height(30.dp)
            .background(Color.White)
            .border(1.dp, GreenGfg),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
  
    ) {
        Text(text = "This Is Item Number $number", color = GreenGfg)
    }
}
  
@Composable
fun LazyColumnExample(numbers: Array<Int>) {
    LazyColumn(
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // item places one item on the LazyScope
        item {
            ColumnItem(number = 0)
        }
  
        // items(count) places number of items supplied 
        // as count and gives current count in the lazyItemScope
        items(10) {currentCount->
            ColumnItem(number = currentCount)
        }
  
        // items(list/array) places number of items
        // same as the size of list/array and gives 
        // current list/array item in the lazyItemScope
        items(numbers) {arrayItem->
            ColumnItem(number = arrayItem)
        }
  
        // items(list/array) places number of 
        // items same as the size of list/array 
        // and gives current list/array item and 
        // currentIndex in the lazyItemScope
        itemsIndexed(numbers) { index, item ->
            ColumnItem(number = index)
        }
    }
}
  
  
// add the annotation, 
// since [LazyVerticalGrid] is Experimental Api
@ExperimentalFoundationApi
@Composable
fun GridExample(numbers: Array<Int>) {
    // Lazy Vertical grid
    LazyVerticalGrid(
        
        // fix the item in one row to be 2.
        cells = GridCells.Fixed(2),
  
        contentPadding = PaddingValues(8.dp),
  
        ) {
        item {
            RowItem(number = 0)
        }
        items(10) {
            RowItem(number = it)
        }
        items(numbers) {
            RowItem(number = it)
        }
        itemsIndexed(numbers) { index, item ->
            RowItem(number = index)
        }
    }
}


Now run the app on an emulator or phone.

Output:

Get the complete code from GitHub.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads