Флажок в Jetpack Compose не обновляется со значением состояния
Я создаю список данных для многократного выбора, а также хочу добавить функциональность, добавив опцию «Выбрать все», чтобы выбрать/отменить выбор всех элементов одновременно.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я проверяю конкретный элемент, он проверяется/снимается, и значение состояния сохраняется там в этой составной области функции, но когда я выбираю весь элемент списка и обновляю значение в списке, это не отражается на " Выбрать все» и наоборот.
Я делюсь здесь своим кодом для созданной мной составной функции.
- Компонуемый для флажка
@Composable
private fun CheckBox(
modifier: Modifier = Modifier,
isChecked: Boolean = false,
checkedColor: Color = MaterialTheme.colors.primary,
checkMarkColor: Color = Color.White,
unCheckedColor: Color = outerSpaceTransparent50,
size: Dp = 24.dp,
onCheckChanged: OnCheckChangedListener = {}
) {
Surface(
color = Color.Transparent,
modifier = Modifier.padding(10.dp)
) {
Surface(color = if (isChecked) checkedColor else Color.Transparent,
modifier = modifier
.noRippleClickable {
onCheckChanged(!isChecked)
}
.size(size)
.border(width = 2.dp, color = if (isChecked) checkedColor else unCheckedColor, shape = MaterialTheme.shapes.small), shape = MaterialTheme.shapes.small) {
AnimatedVisibility(
visible = isChecked,
enter = fadeIn(),
exit = fadeOut()
) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = null,
modifier = Modifier
.size(size)
.padding(4.dp),
tint = checkMarkColor
)
}
}
}
}
- Компонуемый для TitleText
@Composable
fun TitleText(
modifier: Modifier = Modifier,
title: String,
color: Color = outerSpace,
fontSize: TextUnit = 16.sp,
fontWeight: FontWeight = FontWeight.Normal,
overflow: TextOverflow = TextOverflow.Clip,
maxLines: Int = Int.MAX_VALUE,
textAlign: TextAlign = TextAlign.Start
) {
Text(
modifier = modifier,
textAlign = textAlign,
text = title,
overflow = overflow,
maxLines = maxLines,
style = MaterialTheme.typography.h2
.copy(
color = color,
fontSize = fontSize,
fontWeight = fontWeight
)
)
}
- Компонуемый для флажка с заголовком
@Composable
fun CheckBoxTitle(
modifier: Modifier = Modifier,
isChecked: Boolean = false,
title: String, maxLines: Int = 1,
overflow: TextOverflow = TextOverflow.Ellipsis,
onCheckChanged: OnCheckChangedListener = {}
) {
val checkedState = remember {
mutableStateOf(isChecked)
}
Surface(color = Color.White, modifier = modifier
.fillMaxWidth()
.noRippleClickable {
checkedState.value = !checkedState.value
onCheckChanged(checkedState.value)
}) {
Row(modifier = Modifier.padding(horizontal = 20.dp, vertical = 3.dp), horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) {
CheckBox(isChecked = checkedState.value, onCheckChanged = { value ->
checkedState.value = value
onCheckChanged(value)
})
TitleText(title = title,
color = if (checkedState.value) MaterialTheme.colors.primary else outerSpace,
overflow = overflow, fontWeight = if (checkedState.value) FontWeight.SemiBold else FontWeight.Normal, maxLines = maxLines)
}
}
}
И вот я тестирую в режиме предварительного просмотра
private data class CheckBoxTest(val text: String, var isSelected: Boolean = false, val id: String = UUID.randomUUID().toString())
@Preview(showBackground = true)
@Composable
private fun CheckBoxTitlePreview() {
val dataList = SnapshotStateList<CheckBoxTest>().apply {
add(CheckBoxTest("Management"))
add(CheckBoxTest("Development"))
add(CheckBoxTest("Finance"))
add(CheckBoxTest("QA Team"))
}
val allTeamSelected = snapshotFlow { dataList.all { it.isSelected } }.collectAsState(initial = dataList.all { it.isSelected })
AppTheme {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
CheckBoxTitle(
title = "Select All",
isChecked = allTeamSelected.value,
onCheckChanged = { checked ->
val updatedItems = dataList.toList()
updatedItems.forEach { it.isSelected = checked }
dataList.apply {
clear()
addAll(updatedItems)
}
}
)
dataList.forEach { data ->
CheckBoxTitle(
title = data.text,
isChecked = data.isSelected,
onCheckChanged = { checked ->
data.isSelected = checked
val indexOfData = dataList.indexOfFirst { it.id == data.id }
if (indexOfData >= 0) {
dataList.removeAt(indexOfData)
dataList.add(indexOfData, data)
}
}
)
}
}
}
}