Caixas de diálogo para seletores de horário

Os seletores de horário geralmente aparecem em caixas de diálogo. Você pode usar uma implementação relativamente genérica e mínima de uma caixa de diálogo ou uma caixa de diálogo personalizada com mais flexibilidade.

Para mais informações sobre caixas de diálogo em geral, incluindo como usar o estado do seletor de horário, consulte o guia de seletores de horário.

Exemplo básico

A maneira mais simples de criar uma caixa de diálogo para o seletor de horário é criar um elemento combinável que implemente AlertDialog. O snippet a seguir fornece um exemplo de uma caixa de diálogo relativamente mínima usando essa abordagem:

@Composable
fun DialWithDialogExample(
    onConfirm: (TimePickerState) -> Unit,
    onDismiss: () -> Unit,
) {
    val currentTime = Calendar.getInstance()

    val timePickerState = rememberTimePickerState(
        initialHour = currentTime.get(Calendar.HOUR_OF_DAY),
        initialMinute = currentTime.get(Calendar.MINUTE),
        is24Hour = true,
    )

    TimePickerDialog(
        onDismiss = { onDismiss() },
        onConfirm = { onConfirm(timePickerState) }
    ) {
        TimePicker(
            state = timePickerState,
        )
    }
}

@Composable
fun TimePickerDialog(
    onDismiss: () -> Unit,
    onConfirm: () -> Unit,
    content: @Composable () -> Unit
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        dismissButton = {
            TextButton(onClick = { onDismiss() }) {
                Text("Dismiss")
            }
        },
        confirmButton = {
            TextButton(onClick = { onConfirm() }) {
                Text("OK")
            }
        },
        text = { content() }
    )
}

Observe os pontos principais neste snippet:

  1. O elemento combinável DialWithDialogExample envolve TimePicker em uma caixa de diálogo.
  2. TimePickerDialog é um elemento combinável personalizado que cria um AlertDialog com os seguintes parâmetros:
    • onDismiss: uma função chamada quando o usuário dispensa a caixa de diálogo (pelo botão de dispensa ou pela navegação de volta).
    • onConfirm: uma função chamada quando o usuário clica no botão "OK".
    • content: um elemento combinável que mostra o seletor de horário na caixa de diálogo.
  3. O AlertDialog inclui:
    • Um botão de dispensação com a mensagem "Dispensar".
    • Um botão de confirmação com a mensagem "OK".
    • O conteúdo do seletor de horário transmitido como o parâmetro text.
  4. O DialWithDialogExample inicializa o TimePickerState com o horário atual e o transmite para a função TimePicker e onConfirm.
Um seletor de horário em uma AlertDialog que implementa um título, um botão de alternar modo e botões de dispensa e confirmação.
Figura 1. Um seletor de horário em um AlertDialog.

Exemplo avançado

Este snippet demonstra uma implementação avançada de uma caixa de diálogo personalizável do seletor de horário no Jetpack Compose.

@Composable
fun AdvancedTimePickerExample(
    onConfirm: (TimePickerState) -> Unit,
    onDismiss: () -> Unit,
) {

    val currentTime = Calendar.getInstance()

    val timePickerState = rememberTimePickerState(
        initialHour = currentTime.get(Calendar.HOUR_OF_DAY),
        initialMinute = currentTime.get(Calendar.MINUTE),
        is24Hour = true,
    )

    /** Determines whether the time picker is dial or input */
    var showDial by remember { mutableStateOf(true) }

    /** The icon used for the icon button that switches from dial to input */
    val toggleIcon = if (showDial) {
        Icons.Filled.EditCalendar
    } else {
        Icons.Filled.AccessTime
    }

    AdvancedTimePickerDialog(
        onDismiss = { onDismiss() },
        onConfirm = { onConfirm(timePickerState) },
        toggle = {
            IconButton(onClick = { showDial = !showDial }) {
                Icon(
                    imageVector = toggleIcon,
                    contentDescription = "Time picker type toggle",
                )
            }
        },
    ) {
        if (showDial) {
            TimePicker(
                state = timePickerState,
            )
        } else {
            TimeInput(
                state = timePickerState,
            )
        }
    }
}

@Composable
fun AdvancedTimePickerDialog(
    title: String = "Select Time",
    onDismiss: () -> Unit,
    onConfirm: () -> Unit,
    toggle: @Composable () -> Unit = {},
    content: @Composable () -> Unit,
) {
    Dialog(
        onDismissRequest = onDismiss,
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Surface(
            shape = MaterialTheme.shapes.extraLarge,
            tonalElevation = 6.dp,
            modifier =
            Modifier
                .width(IntrinsicSize.Min)
                .height(IntrinsicSize.Min)
                .background(
                    shape = MaterialTheme.shapes.extraLarge,
                    color = MaterialTheme.colorScheme.surface
                ),
        ) {
            Column(
                modifier = Modifier.padding(24.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 20.dp),
                    text = title,
                    style = MaterialTheme.typography.labelMedium
                )
                content()
                Row(
                    modifier = Modifier
                        .height(40.dp)
                        .fillMaxWidth()
                ) {
                    toggle()
                    Spacer(modifier = Modifier.weight(1f))
                    TextButton(onClick = onDismiss) { Text("Cancel") }
                    TextButton(onClick = onConfirm) { Text("OK") }
                }
            }
        }
    }
}

Observe os pontos principais neste snippet:

  1. O elemento combinável AdvancedTimePickerExample cria uma caixa de diálogo personalizável do seletor de horário.
  2. Ele usa um elemento combinável Dialog para ter mais flexibilidade do que o AlertDialog.
  3. A caixa de diálogo inclui um título personalizável e um botão de alternância para alternar entre os modos de discagem e de entrada.
  4. Surface aplica forma e elevação à caixa de diálogo, com IntrinsicSize.Min para largura e altura.
  5. Os layouts Column e Row fornecem os componentes de estrutura da caixa de diálogo.
  6. O exemplo rastreia o modo do seletor usando showDial.
    • Um IconButton alterna entre os modos, atualizando o ícone de acordo com isso.
    • O conteúdo da caixa de diálogo alterna entre TimePicker e TimeInput com base no estado showDial.

Essa implementação avançada oferece uma caixa de diálogo seletora de horário altamente personalizável e reutilizável que pode se adaptar a diferentes casos de uso no app.

Essa implementação aparece da seguinte maneira:

Um seletor de horário em uma caixa de diálogo personalizada que implementa um título, um botão de alternar modo e botões de dispensar e confirmar.
Figura 2. Um seletor de horário em uma caixa de diálogo personalizada.

Outros recursos