Sitemap

LazyColumn With Multi-Header In Jetpack Compose.

3 min readSep 23, 2023
Press enter or click to view image in full size
Photo by Kelly Sikkema on Unsplash

Link For Non-Members

In this article we will see how to make multiple headers for Lazy Column in Jetpack compose.

As you can see in the above video , we have a list of items , and all the items have a type (Animal , Flower, Furniture). We will arrange all the items according to their types and also see show/hide the items.

data class Item(
val id: Int,
val name: String,
val type: String
)

val itemList = listOf(
Item(
1, "Tiger", "Animal"
),
Item(
2, "Lion", "Animal"
),
Item(
3, "Deer", "Animal"
),
Item(
4, "Lotus", "Flower"
),
Item(
5, "Sunflower", "Flower"
),
Item(
6, "Rose", "Flower"
),
Item(
7, "Table", "Furniture"
),
Item(
8, "Chair", "Furniture"
),
Item(
9, "Bed", "Furniture"
),
Item(
10, "Monkey", "Animal"
),
)

First we defined the list of data with their type…

@Composable
fun LazyColumnWithMultiHeaderScreen(
modifier: Modifier
) {

// a mutable map variable , which indicate that item is visible or not
var isShow = remember {
mutableStateMapOf<String, Boolean>()
}

// by default we will store true , all the item will be visible
LaunchedEffect(key1 = Unit) {
isShow = isShow.apply {
itemList.associate { item ->
item.type to true
}.also {
putAll(it)
}
}
}

LazyColumn(
modifier = modifier
.padding(20.dp)
.fillMaxSize()
) {
val groupItems = itemList.groupBy { it.type }
groupItems.forEach { (type, items) ->
item {
Row(
modifier = Modifier
.padding(vertical = 15.dp)
.fillMaxWidth()
.toggleable(
value = isShow[type] == true,
onValueChange = {
isShow[type] = it
},
role = Role.Button
)
) {
Row(
modifier = Modifier.weight(1f)
) {
Text(
text = type,
style = MaterialTheme.typography.headlineLarge.copy(
color = Color.Black,
fontWeight = FontWeight.W700
),

)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = "(${items.size})",
style = MaterialTheme.typography.headlineLarge.copy(
color = Color.Black,
),

)
}
Spacer(modifier = Modifier.width(10.dp))
Icon(
if (isShow[type] == true) Icons.Default.KeyboardArrowDown else Icons.Default.KeyboardArrowUp,
contentDescription = null,
modifier = Modifier.align(CenterVertically)
)
}
}
if (isShow[type] == true)
items(items, key = { it.id }) {
Text(
text = it.name, style = MaterialTheme.typography.bodyLarge.copy(
color = Color.DarkGray
),
modifier = Modifier.padding(top = 10.dp)
)
}
}
}

}
  • As you can see in the above code , First we have defined a isShow variable , which is a mutableStateMapOf<String,Boolean> , which store type (Animals , Flowers , Furniture) and their corresponding true/false value, so that it’s easy to keep track , which item we want to show/hide.
  • After that in the LaunchEffect we apply all the type to true , because by default all the item will be visible.
  • Now in the LazyColumn , first we group the items with their type , As you see with the help of groupBy{} kotlin’s in-built function , it will return Map<String, List<Item>> .
  • After that use forEach loop which will return (type,List<Item>) , In the item{} function , just write your header section with hide/show functionality
  • And In the items{} function , pass your List<Item> data , and it will show all the items corresponding to their type

That’s all for today my friends , Hope you enjoyed and learnt something new from this article.

--

--

Jayant Kumar🇮🇳
Jayant Kumar🇮🇳

Written by Jayant Kumar🇮🇳

Jayant Kumar is a Lead Software Engineer, passionate about building modern Android applications. He shares his expertise in Kotlin, Android, and Compose.