Caixa de seleção

As caixas de seleção permitem que os usuários selecionem um ou mais itens de uma lista. Você pode usar uma caixa de seleção para permitir que o usuário faça o seguinte:

  • Ative ou desative um item.
  • Escolher entre várias opções em uma lista.
  • Indicar concordância ou aceitação.

Anatomia

Uma caixa de seleção consiste nos seguintes elementos:

  • Caixa: é o contêiner da caixa de seleção.
  • Marca de seleção: é o indicador visual que mostra se a caixa de seleção está marcada ou não.
  • Marcador: é o texto que descreve a caixa de seleção.

Estados

Uma caixa de seleção pode estar em um dos três estados:

  • Não selecionada: a caixa de seleção não está marcada. A caixa está vazia.
  • Indeterminado: a caixa de seleção está em um estado indeterminado. A caixa contém um traço.
  • Selecionada: a caixa de seleção está marcada. A caixa contém uma marca de seleção.

A imagem a seguir demonstra os três estados de uma caixa de seleção.

Exemplo de um componente de caixa de seleção em cada um dos três estados: não selecionado, selecionado e indeterminado.
Figura 1. Os três estados de uma caixa de seleção. Desmarcado, indeterminado e marcado.

Implementação

Você pode usar o elemento combinável Checkbox para criar uma caixa de seleção no seu app. Há apenas alguns parâmetros principais para ter em mente:

  • checked: o booleano que captura se a caixa de seleção está marcada ou desmarcada.
  • onCheckedChange(): a função que o app chama quando o usuário toca na caixa de seleção.

O snippet a seguir demonstra como usar o elemento combinável 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"
    )
}

Explicação

Esse código cria uma caixa de seleção que inicialmente está desmarcada. Quando o usuário clica na caixa de seleção, a lambda onCheckedChange atualiza o estado checked.

Resultado

Este exemplo produz o seguinte componente quando não está marcado:

Uma caixa de seleção desmarcada com um rótulo. O texto abaixo dela diz "A caixa de seleção está desmarcada".
Figura 2. Caixa de seleção desmarcada

E esta é a aparência da mesma caixa de seleção quando marcada:

Uma caixa de seleção marcada com um rótulo. O texto abaixo diz "A caixa de seleção está marcada".
Figura 3. Caixa de seleção marcada

Exemplo avançado

Confira um exemplo mais complexo de como implementar caixas de seleção no app. Neste snippet, há uma caixa de seleção principal e uma série de caixas de seleção filhas. Quando o usuário toca na caixa de seleção principal, o app marca todas as caixas de seleção filhas.

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

Explicação

Confira alguns pontos importantes deste exemplo:

  • Gerenciamento de estado:
    • childCheckedStates: uma lista de booleanos usando mutableStateOf() para rastrear o estado marcado de cada caixa de seleção filha.
    • parentState: um ToggleableState cujo valor deriva dos estados das caixas de seleção filhas.
  • Componentes da interface:
    • TriStateCheckbox: é necessário para a caixa de seleção principal, já que tem um parâmetro state que permite definir como indeterminado.
    • Checkbox: usado para cada caixa de seleção filha com o estado vinculado ao elemento correspondente em childCheckedStates.
    • Text: mostra rótulos e mensagens ("Selecionar tudo", "Opção X", "Todas as opções selecionadas").
  • Lógica:
    • A caixa de seleção principal onClick atualiza todas as caixas de seleção secundárias para o oposto do estado principal atual.
    • Cada caixa de seleção filha onCheckedChange atualiza o estado correspondente na lista childCheckedStates.
    • O código mostra "All options selected" quando todas as caixas de seleção filhas estão marcadas.

Resultado

Este exemplo produz o seguinte componente quando todas as caixas de seleção estão desmarcadas.

Uma série de caixas de seleção marcadas com um rótulo.
Figura 4. Caixas de seleção desmarcadas

Da mesma forma, é assim que o componente aparece quando todas as opções estão marcadas, como quando o usuário toca em "Selecionar tudo":

Uma série de caixas de seleção marcadas com um rótulo. O primeiro é marcado como "Selecionar tudo". Há um componente de texto abaixo deles que diz "todas as opções selecionadas".
Figura 5. Caixas de seleção marcadas

Quando apenas uma opção é marcada, a caixa de seleção principal mostra o estado indeterminado:

Uma série de caixas de seleção marcadas com um rótulo. Todos, exceto um, estão desmarcados. A caixa de seleção "Selecionar tudo" está indeterminada, mostrando um traço.
Figura 6. Caixa de seleção indeterminada

Outros recursos