Casilla de verificación

Las casillas de verificación permiten que los usuarios seleccionen uno o más elementos de una lista. Puedes usar una casilla de verificación para permitir que el usuario haga lo siguiente:

  • Activar o desactivar un elemento
  • Seleccionar entre varias opciones en una lista
  • Indicar acuerdo o aceptación

Anatomía

Una casilla de verificación consta de los siguientes elementos:

  • Cuadro: Es el contenedor de la casilla de verificación.
  • Marca: Es el indicador visual que muestra si la casilla de verificación está seleccionada o no.
  • Etiqueta: Es el texto que describe la casilla de verificación.

Estados

Una casilla de verificación puede estar en uno de los siguientes tres estados:

  • No seleccionada: La casilla de verificación no está seleccionada. El cuadro está vacío.
  • Indeterminado: La casilla de verificación está en un estado indeterminado. El cuadro contiene un guion.
  • Seleccionada: La casilla de verificación está seleccionada. El cuadro contiene una marca de verificación.

En la siguiente imagen, se muestran los tres estados de una casilla de verificación.

Ejemplo de un componente de casilla de verificación en cada uno de sus tres estados: no seleccionado, seleccionado y no determinado.
Figura 1. Los tres estados de una casilla de verificación (no seleccionada, indeterminada y seleccionada)

Implementación

Puedes usar el elemento componible Checkbox para crear una casilla de verificación en tu app. Solo debes tener en cuenta algunos parámetros clave:

  • checked: Es el valor booleano que captura si la casilla de verificación está marcada o desmarcada.
  • onCheckedChange(): Es la función que llama la app cuando el usuario presiona la casilla de verificación.

En el siguiente fragmento, se muestra cómo usar el elemento componible Checkbox:

@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"
    )
}

Explicación

Este código crea una casilla de verificación que inicialmente está desmarcada. Cuando el usuario hace clic en la casilla de verificación, la expresión lambda onCheckedChange actualiza el estado checked.

Resultado

En este ejemplo, se produce el siguiente componente cuando está desmarcado:

Una casilla de verificación sin marcar con una etiqueta. El texto debajo dice "La casilla de verificación no está marcada".
Figura 2. Casilla de verificación desmarcada

Así es como aparece la misma casilla de verificación cuando está marcada:

Una casilla de verificación marcada con una etiqueta. El texto debajo dice "La casilla de verificación está marcada".
Figura 3: Casilla de verificación marcada

Ejemplo avanzado

A continuación, se muestra un ejemplo más complejo de cómo puedes implementar casillas de verificación en tu app. En este fragmento, hay una casilla de verificación superior y una serie de casillas de verificación secundarias. Cuando el usuario presiona la casilla de verificación superior, la app marca todas las casillas de verificación secundarias.

@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")
    }
}

Explicación

Estos son varios puntos que debes tener en cuenta en este ejemplo:

  • Administración de estados:
    • childCheckedStates: Es una lista de valores booleanos que usa mutableStateOf() para hacer un seguimiento del estado marcado de cada casilla de verificación secundaria.
    • parentState: Es un ToggleableState cuyo valor se deriva de los estados de las casillas de verificación secundarias.
  • Componentes de la IU:
    • TriStateCheckbox: Es necesario para la casilla de verificación superior, ya que tiene un parámetro state que te permite configurarlo como indeterminado.
    • Checkbox: Se usa para cada casilla de verificación secundaria con su estado vinculado al elemento correspondiente en childCheckedStates.
    • Text: Muestra etiquetas y mensajes ("Seleccionar todo", "Opción X", "Se seleccionaron todas las opciones").
  • Lógica:
    • onClick de la casilla de verificación superior actualiza todas las casillas de verificación secundarias al estado opuesto del estado superior actual.
    • onCheckedChange de cada casilla de verificación secundaria actualiza su estado correspondiente en la lista childCheckedStates.
    • El código muestra "All options selected" cuando se marcan todas las casillas de verificación secundarias.

Resultado

En este ejemplo, se produce el siguiente componente cuando todas las casillas de verificación están desmarcadas.

Es una serie de casillas de verificación etiquetadas sin marcar con una etiqueta.
Figura 4. Casillas de verificación desmarcadas

Del mismo modo, así es como aparece el componente cuando se marcan todas las opciones, como cuando el usuario presiona Seleccionar todo:

Una serie de casillas de verificación etiquetadas marcadas con una etiqueta. La primera está marcada como "Seleccionar todo". Debajo de ellos, hay un componente de texto que dice "Se seleccionaron todas las opciones".
Figura 5: Casillas de verificación marcadas

Cuando solo se marca una opción, la casilla de verificación superior muestra el estado indeterminado:

Una serie de casillas de verificación etiquetadas sin marcar con una etiqueta. Todas, excepto una, están desmarcadas. La casilla de verificación etiquetada como "Seleccionar todo" es indeterminada y muestra un guion.
Figura 6: Casilla de verificación indeterminada

Recursos adicionales