Unicorn Commerce — Coding Bootcamp — The Unicorn Fullstack Professional Developer Guide to Modern Android Development — Part 6

Unicorn Commerce — Modern Android Development Part 6— Jetpack Compose Lazy Layouts — LazyColumn, LazyRow, and LazyGrid

Arunabh Das
Developers Inc
5 min readMar 8, 2023

--

This part continues from where we left off in Part5

Please use the feature/develop_starter_kit_part6 branch to follow along

Alternatively, one may use the starter-kit-part6 release to follow along

In this part, we are going to cover LazyColumn, LazyRow, and LazyGrid

LazyColumn, LazyRow, and LazyGrid composes only that which is visible in the viewport, which increases the Responsiveness and Performance of the app.

LazyRow, like Row, is a horizontal scrollable list.

LazyColumn, like Column, is a vertical scrollable list.

LazyColumns and LazyRows can use itemsIndexed() instead of Items() if index of the item is needed in the list

Index and Item can be used in the lambda expression

Compose provides 2 types of grids — LazyVerticalGrid and LazyHorizontalGrid

Let’s implement the list of tshirts for sale on the Unicorn Commerce app using LazyRow and LazyColumn on the CollectionsScreen.

First, let’s create a ProductCategories.kt file in $PROJECT_ROOT/src/main/app/unicornapp/mobile/android/unicorn/data package

/**
* ProductCategories.kt
*/

val productCategories = listOf<String>(
"Tshirts",
"Men's Apparel",
"Women's Apparel",
"Shoes"
)

Next, we need to create a Product.kt file containing the Product data class in $PROJECT_ROOT/src/main/app/unicornapp/mobile/android/unicorn/data package

/**
* Product.kt
*/
data class Product (
val name: String,
val price: String,
val description: String,
val image: Int
)

val products = listOf<Product>(
Product("Don't Panic", "$29.99", "Don't Panic Tshirt", R.drawable.tshirt_1),
Product("Got Milky Way", "$39.99", "Got Milky Way Tshirt", R.drawable.tshirt_2),
Product("Starry Nights", "$49.99", "Starry Nights Tshirt", R.drawable.tshirt_3),

)

We may now improve the ItemProduct.kt file in $PROJECT_ROOT/src/main/app/unicornapp/mobile/android/unicorn/ui/screens to include the Product data class as below

/**
* ItemProduct.kt
*/
@Composable
fun ItemProduct(
navController: NavController,
product: Product
) {
val context = LocalContext.current
Column(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start,
modifier = Modifier
.fillMaxWidth()
/* TODO-FIXME-CLEANUP .background(Color(0xFF495E57)) */
) {
Text(
modifier = Modifier
.clickable {
navController.navigate(route = Screen.HomeDetailScreen.route)
}
.padding(20.dp),
text = product.name,
fontSize = MaterialTheme.typography.titleLarge.fontSize,
color = Color.White,
fontWeight = FontWeight.Bold,
)
Text(
modifier = Modifier
.clickable {
navController.navigate(route = Screen.HomeDetailScreen.route)

}
.padding(20.dp),
text = product.description,
fontSize = MaterialTheme.typography.titleLarge.fontSize,
color = Color.White,
fontWeight = FontWeight.Bold
)
Row(
Modifier
.fillMaxWidth()
.padding(20.dp), horizontalArrangement = Arrangement.Start) {
Text(
text = product.price,
Modifier.width(200.dp),
fontSize = 14.sp,
color = Color.White,
fontWeight = FontWeight.Light
)
Image(
painter = painterResource(id = product.image),
contentDescription = "",
Modifier
.height(200.dp)
.clip(RoundedCornerShape(20.dp)),
)
}
}
}

@Preview
@Composable
fun ItemProductPreview() {
ItemProduct(
navController = rememberNavController(),
Product("Tshirt", "$29.99", "Tshirt for sale", R.drawable.tshirt_1)
)
}

We may now implment the CollectionsScreen.kt using LazyRow and LazyColumn as below

/**
* CollectionsScreen.kt
*/


@Composable
fun CollectionsScreen(
navController: NavController,
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painterResource(
id = R.drawable.banner_bg_6),
contentDescription = "",
contentScale = ContentScale.FillBounds,
modifier = Modifier.matchParentSize()
)
Column(
Modifier.padding(
top = 70.dp,
bottom = 50.dp
),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
modifier = Modifier.clickable {
navController.navigate(Screen.HomeScreen.route) {
popUpTo(Screen.HomeScreen.route) {
inclusive = true
}
}
},
text = "Collections",
color = Color.White,
fontSize = MaterialTheme.typography.titleSmall.fontSize,
fontWeight = FontWeight.Bold
)

Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.SpaceEvenly
) {
LazyRow {
items(productCategories) { productCategory ->
ItemCategory(category = productCategory)
}
}
Divider(
modifier = Modifier.padding(8.dp),
color = Color.Gray,
thickness = 1.dp
)
LazyColumn {
items(products) {product ->
ItemProduct(
navController = navController,
product = product
)
Divider(
modifier = Modifier.padding(8.dp),
color = Color.Gray,
thickness = 1.dp
)
}
}
}
}
}
}

@Preview
@Composable
fun CollectionsScreenPreview() {
CollectionsScreen(navController = rememberNavController())
}

This gives us the list of product categories in a LazyRow and the list of products in a LazyColumn as below

LazyRow and LazyColumn implementation

In addition to our Collections screen, we may create a SpringCollections screen as below

@Composable
fun SpringCollectionsScreen(
navController: NavController
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painterResource(
id = R.drawable.banner_bg_6),
contentDescription = "",
contentScale = ContentScale.FillBounds,
modifier = Modifier.matchParentSize()
)
Text(
modifier = Modifier.clickable {
navController.navigate(Screen.HomeScreen.route) {
popUpTo(Screen.HomeScreen.route) {
inclusive = true
}
}
},
text = "SpringCollectionScreen",
color = Color.White,
fontSize = MaterialTheme.typography.titleSmall.fontSize,
fontWeight = FontWeight.Bold
)
}

}

@Preview
@Composable
fun SpringCollectionsScreenPreview() {
SpringCollectionsScreen(navController = rememberNavController())
}

We may now implement LazyVerticalGrid in SpringCollectionsScreen as below


@Composable
fun SpringCollectionsScreen(
navController: NavController
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painterResource(
id = R.drawable.banner_bg_6),
contentDescription = "",
contentScale = ContentScale.FillBounds,
modifier = Modifier.matchParentSize()
)
LazyVerticalGrid(
modifier = Modifier.padding(
top = 90.dp,
bottom = 50.dp
),
columns = GridCells.Adaptive(150.dp)
) {
items(500) { number ->
MyGridCell(number)
}
}
}
}

@Composable
fun MyGridCell(number: Int) {
Card(
modifier = Modifier.padding(8.dp),
elevation = 20.dp
) {
Box(
modifier = Modifier.aspectRatio(1f),
contentAlignment = Alignment.Center
) {
Text(
text = "Item " + number,
fontSize = 20.sp
)
Image(
painter = painterResource(id = R.drawable.tshirt_2),
contentDescription = "",
Modifier
.height(200.dp)
.clip(RoundedCornerShape(20.dp)),
)
}
}
}

@Preview
@Composable
fun SpringCollectionsScreenPreview() {
SpringCollectionsScreen(navController = rememberNavController())
}

This gives us the below layout for the SpringCollections screen

Create a color theme called UnicornAppColor in Color.kt as below


val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Olive100 = Color(0XFF777d68)
val Maroon100 = Color(0xFFB60F46)

val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Transparent = Color(0xFF00000000)

object UnicornApppColor {
val one = Color(0xFFEEE299)
val two = Color(0xFFCDA362)
val three = Color(0xFFAB6B49)
val four = Color(0xFF733E4F)
val five = Color(0xFF402C44)
val graphene = Color(0xFF333333)
}

Modify Theme.kt to use UnicornAppColor theme as follows

private val DarkColorScheme = darkColorScheme(
primary = UnicornApppColor.four,
onPrimary = UnicornApppColor.one,
secondary = UnicornApppColor.five,
onSecondary = UnicornApppColor.two,
tertiary = UnicornApppColor.graphene,
onTertiary = Color.White
)

--

--

Arunabh Das
Developers Inc

Sort of an executive-officer-of-the-week of a-techno-syndicalist commune. Cypherpunk, techno-idealist, peacenik, spiritual, humanist