In this Jetpack compose tutorial we will learn how to Create Expandable Listview with Jetpack compose in Android application. Expanded Listview is a list where we can show some data and hide some data .Basically its a two-level parent-child list where children are hide until the list item is expanded.
Let's get started
Step 1: Create android application in android studio
Step 2: Follow step for setup Jetpack Compose with Android Studio
In this example we are managing the data inside listview with Viewmodel and kotlin data classes
Lets create a Expanded List Item data class
data class User( val id: String = "", val name: String = "", val emailId: String = "" ) data class ExpandedListItem(val data: User, val index: Int, var expanded: Boolean = false) |
View Model
package com.example.jetpack.viewmodels import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.example.jetpack.ExpandedListItem import com.example.jetpack.datamodels.User import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch class UserViewModel(appObj: Application) : AndroidViewModel(appObj) { private val _users = MutableStateFlow(listOf()) val users: StateFlow> get() = _users fun changeItemValue(index: Int, expanded: Boolean) { val list = _users.value.toMutableList() list[index] = list[index].copy(expanded = expanded) _users.value = list.toList() } init { fetchUsers() } private fun fetchUsers() { viewModelScope.launch { val userList = arrayListOf( ExpandedListItem( data = User(id = "1", name = "Ankit Singh", emailId = "an@gmail.com"), index = 0 ), ExpandedListItem( data = User(id = "2", name = "Neha Shaw", emailId = "ne@gmail.com"), index = 1 ), ExpandedListItem( data = User(id = "3", name = "Arpita Ghosh", emailId = "ar@gmail.com"), index = 2 ), ExpandedListItem( data = User(id = "4", name = "Akash Tiwari", emailId = "ak@gmail.com"), index = 3 ), ExpandedListItem( data = User(id = "5", name = "Anisha Tiwari", emailId = "an@gmail.com"), index = 4 ), ExpandedListItem( data = User(id = "6", name = "Rowdy Rathore", emailId = "ro@gmail.com"), index = 5 ), ExpandedListItem( data = User(id = "7", name = "Jit Singh", emailId = "ji@gmail.com"), index = 6 ), ExpandedListItem( data = User(id = "8", name = "Pravin Raj", emailId = "pr@gmail.com"), index = 7 ), ExpandedListItem( data = User(id = "9", name = "Sneha Rao", emailId = "sn@gmail.com"), index = 8 ), ExpandedListItem( data = User(id = "10", name = "Ranjana Rathore", emailId = "ran@gmail.com"), index = 9 ), ExpandedListItem( data = User(id = "11", name = "Kamala Rathore", emailId = "ka@gmail.com"), index = 10 ), ExpandedListItem( data = User(id = "12", name = "Ranjani Rathore", emailId = "raj@gmail.com"), index = 11 ), ExpandedListItem( data = User(id = "13", name = "XYZ Rathore", emailId = "xyz@gmail.com"), index = 12 ), ExpandedListItem( data = User(id = "14", name = "ZAR Rathore", emailId = "zar@gmail.com"), index = 13 ) ) _users.emit(userList) } } } |
Here we have used stateFlow which emits list of user whenever user data will changed that can be observed while showing list items.
Lets create UI to display data inside listview with exapandable
@Composable fun ExpandableListDemo(userViewModel: UserViewModel) { val users = userViewModel.users.collectAsState() JetPackTheme() { LazyColumn(contentPadding = PaddingValues(horizontal = 16.dp)) { itemsIndexed(items = users.value, itemContent = { pos, item -> Column(content = { ExpandedListItemView( item, onButtonClicked = { id: String, expanded: Boolean, index: Int -> userViewModel.changeItemValue( index, expanded = expanded ) }) if (item.expanded) { UserListItemView(user = item.data) } }) }) } } } @Composable fun ExpandedListItemView( item: ExpandedListItem, onButtonClicked: ((id: String, expanded: Boolean, index: Int) -> Unit)? = null ) { Row( content = { Text(item.data.name, modifier = Modifier.weight(1F), fontWeight = FontWeight.Bold) Icon( imageVector = if (item.expanded) Icons.Default.ArrowDropUp else Icons.Default.ArrowDropDown, contentDescription = "image", tint = Color.Black, modifier = Modifier .size(30.dp) .clickable(onClick = { onButtonClicked?.invoke(item.data.id, !item.expanded, item.index) }) ) }, modifier = Modifier .fillMaxWidth() .padding(top = 16.dp) ) } @Composable fun UserListItemView(user: User) { Column(content = { Text(text = user.emailId, color = Color.Gray) }) } |
To display the header list item data we will use below compose function
@Composable fun ExpandedListItemView( item: ExpandedListItem, onButtonClicked: ((id: String, expanded: Boolean, index: Int) -> Unit)? = null ) { Row( content = { Text(item.data.name, modifier = Modifier.weight(1F), fontWeight = FontWeight.Bold) Icon( imageVector = if (item.expanded) Icons.Default.ArrowDropUp else Icons.Default.ArrowDropDown, contentDescription = "image", tint = Color.Black, modifier = Modifier .size(30.dp) .clickable(onClick = { onButtonClicked?.invoke(item.data.id, !item.expanded, item.index) }) ) }, modifier = Modifier .fillMaxWidth() .padding(top = 16.dp) ) } |
When we tap on the header item we are showing the child data with the below compose function
@Composable fun UserListItemView(user: User) { Column(content = { Text(text = user.emailId, color = Color.Gray) }) } |
Now let's run the application, you can see the data inside expandable listview, when we tap on header list item, it will expand and display the child list items.
Full code
package com.example.jetpack import android.os.Bundle import android.view.WindowManager import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModelProvider import com.example.jetpack.datamodels.User import com.example.jetpack.ui.theme.JetPackTheme import com.example.jetpack.viewmodels.UserViewModel class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) val userViewModel = ViewModelProvider(this).get(UserViewModel::class.java) setContent { ExpandableListDemo(userViewModel) } } } data class ExpandedListItem(val data: User, val index: Int, var expanded: Boolean = false) @Composable fun ExpandableListDemo(userViewModel: UserViewModel) { val users = userViewModel.users.collectAsState() JetPackTheme() { LazyColumn(contentPadding = PaddingValues(horizontal = 16.dp)) { itemsIndexed(items = users.value, itemContent = { pos, item -> Column(content = { ExpandedListItemView( item, onButtonClicked = { id: String, expanded: Boolean, index: Int -> userViewModel.changeItemValue( index, expanded = expanded ) }) if (item.expanded) { UserListItemView(user = item.data) } }) }) } } } @Composable fun ExpandedListItemView( item: ExpandedListItem, onButtonClicked: ((id: String, expanded: Boolean, index: Int) -> Unit)? = null ) { Row( content = { Text(item.data.name, modifier = Modifier.weight(1F), fontWeight = FontWeight.Bold) Icon( imageVector = if (item.expanded) Icons.Default.ArrowDropUp else Icons.Default.ArrowDropDown, contentDescription = "image", tint = Color.Black, modifier = Modifier .size(30.dp) .clickable(onClick = { onButtonClicked?.invoke(item.data.id, !item.expanded, item.index) }) ) }, modifier = Modifier .fillMaxWidth() .padding(top = 16.dp) ) } @Composable fun UserListItemView(user: User) { Column(content = { Text(text = user.emailId, color = Color.Gray) }) } |
Conclusion: In this jetpack compose tutorial we covered how to create expandable listview with jetpack compose and handle the expand and collapse the list items.
Article Contributed By :
|
|
|
|
2727 Views |