Reputation: 51
I have been scratching my head over this problem. I have a data class representing items that can be selected(or unselected).
data class FilterItem(
val name: String,
val isSelected: Boolean
)
I have created a mutableStateList of items in my ViewModel which creates a list and that can be accessed by composable.
val filterList = mutableStateListOf<FilterItem>()
filterList.addAll(listOf(
FilterItem("ABC", isSelected = false),
FilterItem("DEF", isSelected = false)
))
My composable accesses the list -
FilterLayout(
filterList = viewModel.filterList
)
@Composable
fun FilterLayout(
filterList: SnapshotStateList<FilterItem>
){
.....
itemsIndexed(filterList)) { index, it ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 15.dp)
.clickable {
setSelected(it.name)
},
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = it.name
)
Log.d("debug", "selected " + it.isSelected + " " + it.name)
Checkbox(
isSelected = it.isSelected,
onCheckedChange = {},
modifier = Modifier.size(25.dp)
)
}
}
}
The problem here is, when clicked on an item, setSelected gets called, which updates the list (till here it's good). The change is reflected in logcat, when I print my message. That means list is getting updated, and recomposed. I can see the item getting selected in logs, but Ui doesn't reflect that. Sometimes it does reflect instantly and sometimes I have to click on other rows to trigger recomposition and then it reflects.
Below is my update function -
fun setSelected(name: String) {
viewModelScope.launch {
val index = filterList.indexOfFirst { name == it.name }
filterList[index] = filterList[index].copy(isSelected = !filterList[index].isSelected)
}
}
I tried replacing the checkbox with if-else block,
if(it.isSelected) this icon else other icon
still facing the same issue -
Upvotes: 1
Views: 2134
Reputation: 1128
When clicking the check box, nothing happens because its onCheckedChange does nothing. But when clicking the row, it updates successfully.
@Composable
fun FilterLayout(
filterList: SnapshotStateList<FilterItem>,
setSelected: (String) -> Unit,
) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
itemsIndexed(filterList) { index, filterItem ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 15.dp)
.clickable {
setSelected(filterItem.name)
},
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = filterItem.name
)
Log.d("debug", "selected " + filterItem.isSelected + " " + filterItem.name)
Checkbox(
checked = filterItem.isSelected,
// set on checked change to update selected state
onCheckedChange = { setSelected(filterItem.name) },
modifier = Modifier.size(25.dp)
)
}
}
}
}
Upvotes: 0