android-checkbox.md

#Checkbox

Checkboxes let users select one or more items from a list. You might use a checkbox to let the user do the following:

Note: Use checkboxes instead of switches or radio buttons if the user can select multiple options in a list.

#Anatomy

A checkbox consists of the following elements:


#States

A checkbox can be in one of three states:

  1. Unselected: The checkbox is not selected. The box is empty.
  2. Indeterminate: The checkbox is in an indeterminate state. The box contains a dash.
  3. Selected: The checkbox is selected. The box contains a checkmark.

Figure 1. The three states of a checkbox: Unselected, indeterminate, and selected.


#Implementation

You can use the Checkbox composable to create a checkbox in your app. There are just a few key parameters to keep in mind:

The following snippet demonstrates how to use the Checkbox composable:

kotlin@Composable
fun CheckboxMinimalExample() {
    var checked by remember { mutableStateOf(true) }

    Row(
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(
            "Minimal checkbox"
        )
        Checkbox(
            checked = checked,
            onCheckedChange = { checked = it }
        )
    }

    Text(
        if (checked) "Checkbox is checked" else "Checkbox is unchecked"
    )
}

#Explanation

This code creates a checkbox that is initially unchecked. When the user clicks on the checkbox, the onCheckedChange lambda updates the checked state.


#Result

This example produces the following component when unchecked:

Figure 2. Unchecked checkbox (Text reads: 'Checkbox is unchecked')

And this is how the same checkbox appears when checked:

Figure 3. Checked checkbox (Text reads: 'Checkbox is checked')


#Advanced Example

The following is a more complex example of how you can implement checkboxes in your app. In this snippet, there is a parent checkbox and a series of child checkboxes. When the user taps the parent checkbox, the app checks all child checkboxes.

kotlin@Composable
fun CheckboxParentExample() {
    // Initialize states for the child checkboxes
    val childCheckedStates = remember { mutableStateListOf(false, false, false) }

    // Compute the parent state based on children's states
    val parentState = when {
        childCheckedStates.all { it } -> ToggleableState.On
        childCheckedStates.none { it } -> ToggleableState.Off
        else -> ToggleableState.Indeterminate
    }

    Column {
        // Parent TriStateCheckbox
        Row(
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text("Select all")
            TriStateCheckbox(
                state = parentState,
                onClick = {
                    // Determine new state based on current state
                    val newState = parentState != ToggleableState.On
                    childCheckedStates.forEachIndexed { index, _ ->
                        childCheckedStates[index] = newState
                    }
                }
            )
        }

        // Child Checkboxes
        childCheckedStates.forEachIndexed { index, checked ->
            Row(
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text("Option ${index + 1}")
                Checkbox(
                    checked = checked,
                    onCheckedChange = { isChecked ->
                        // Update the individual child state
                        childCheckedStates[index] = isChecked
                    }
                )
            }
        }
    }

    if (childCheckedStates.all { it }) {
        Text("All options selected")
    }
}

#Explanation

The following are several points you should note from this example:

Note: If you want to have a checkbox with an indeterminate state, you must use TriStateCheckbox. This is because it has a state parameter of type ToggleableState, whereas Checkbox does not.

#Result

This example produces the following component when all checkboxes are unchecked:

Figure 4. Unchecked checkboxes

Likewise, this is how the component appears when all options are checked, as when the user taps select all:

Figure 5. Checked checkboxes (Text reads: 'All options selected')

When only one option is checked the parent checkbox displays the indeterminate state:

Figure 6. Indeterminate checkbox (The 'Select all' box displays a dash)