Nested State for checkbox in jetpack compose

1.9k views Asked by At

I have face problem related to states in jetpack compose. Problem is that I have list that contains questions. Some question need radio button for single selection and some question need checkbox for multiple selection. see below image..

Screen shot example.

Raio Buttino Code

View Model class

private val _isRadioChecked = mutableStateListOf<ResearchQuestion>()
val optionState: List<ResearchQuestion> = _isRadioChecked

fun setRadioChecked(index: Int,isChecked: ResearchQuestion) {
    _isRadioChecked[index] = isChecked
}
fun setRadioChecked(isChecked: ResearchQuestion) {
    _optionState.add(isChecked)
}

Data class -> ResearchQuestion

val question: String = "",
val isMultipleChoice: Boolean = false,
val selectedMultipleOption: Set<Int> = emptySet(),
val selectOption: Int = -1,

Compose Screen -> Radio Button compose

@Composable
fun CodeRadioButton(
  options: List<String>,
  selectedOption: Int,
  onOptionSelected: (Int) -> Unit
) {
  options.forEachIndexed { index, option ->
    Row(
        modifier = Modifier
            .padding(vertical = 5.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        RadioButton(
            modifier = Modifier
                .size(15.dp)
                .padding(start = 15.dp),
            selected = (index == selectedOption),
            onClick = {
                onOptionSelected(index)
            }
        )
        Spacer(modifier = Modifier.padding(horizontal = 15.dp))
        Text(
            modifier = Modifier
                .clickable {
                    onOptionSelected(index)
                },
            text = option,
            style = MaterialTheme.typography.body2
        )
        Spacer(modifier = Modifier.padding(vertical = 10.dp))
    }
  }
 }

Compose Screen -> CheckBox Button compose

@Composable
fun CodeMultipleChoice(
  options: List<String>,
  isMultipleChecked: Set<Int>,
  onMultiOptionSelected: (List<Int>) -> Unit,
) {

  options.forEachIndexed { index, option ->
    Row(
        modifier = Modifier
            .padding(vertical = 5.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Checkbox(
            modifier = Modifier
                .size(15.dp)
                .padding(start = 15.dp),
            checked = false, //State did not work
            onCheckedChange = {
                //State did not work
            },
            colors = CheckboxDefaults.colors(
                checkmarkColor = Color.White
            )
        )
        Spacer(modifier = Modifier.padding(horizontal = 15.dp))
        Text(
            modifier = Modifier
                .clickable {
                    
                },
            text = option,
            style = MaterialTheme.typography.body2
        )
        Spacer(modifier = Modifier.padding(vertical = 10.dp))
    }
  }
}

Noted: Radio button work perfectly but multiple selection(checkbox) state did not work. I create mutableStateList0f() but if check checkbox other question which having multiple question are also change.

1

There are 1 answers

0
commandiron On BEST ANSWER

I marked the lines I changed as 'changed line'

@Composable
fun CodeMultipleChoice(
    options: List<String>,
    isMultipleChecked: Set<Int>,
    onMultiOptionSelected: (List<Int>) -> Unit,
) {

    var multipleChecked by remember { mutableStateOf(isMultipleChecked)}//*Changed line

    options.forEachIndexed { index, option ->
        Row(
            modifier = Modifier
                .padding(vertical = 5.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Checkbox(
                modifier = Modifier
                    .size(15.dp)
                    .padding(start = 15.dp),
                checked = multipleChecked.contains(index), //*Changed line
                onCheckedChange = { //*Changed line
                    if(it){
                        multipleChecked = multipleChecked + index
                    } else{
                        multipleChecked = multipleChecked - index
                    }
                },
                colors = CheckboxDefaults.colors(
                    checkmarkColor = Color.White
                )
            )
            Spacer(modifier = Modifier.padding(horizontal = 15.dp))
            Text(
                modifier = Modifier
                    .clickable {

                    },
                text = option,
                style = MaterialTheme.typography.body2
            )
            Spacer(modifier = Modifier.padding(vertical = 10.dp))
        }
    }
}