Selectores de horarios

Los selectores de hora permiten a los usuarios seleccionar una hora. Puedes usar los elementos componibles TimePicker y TimeInput para implementar un selector de hora en tu app.

Tipos

Existen dos tipos de selectores de tiempo:

  • Dial: Permite a los usuarios establecer una hora moviendo un controlador alrededor de un dial.
  • Entrada: Permite que los usuarios configuren una hora con el teclado.

En la siguiente imagen, se proporciona un ejemplo de un selector de hora de marcado a la izquierda y un selector de hora de entrada a la derecha:

Un dial y un selector de hora de entrada.
Figura 1: Un dial y un selector de hora de entrada.

Superficie de la API

Para implementar un selector de hora, usa el elemento TimePicker o TimeInput que admite composición:

  • TimePicker: Implementa un selector de hora de marcado.
  • TimeInput: Implementa un selector de hora de entrada.

Estado

Para TimePicker y TimeInput, también debes pasar un TimePickerState. Esto te permite establecer la hora seleccionada predeterminada que aparece en el selector. También captura la hora que el usuario seleccionó con el selector.

Diálogo

Los selectores de hora aparecen en diálogos. En los ejemplos de esta guía, no se usan diálogos. Para ver ejemplos que sí usan diálogos, consulta la guía Diálogos para selectores de tiempo.

Selector de hora de marcado

En este fragmento, se muestra cómo implementar un selector de hora básico.

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

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

    Column {
        TimePicker(
            state = timePickerState,
        )
        Button(onClick = onDismiss) {
            Text("Dismiss picker")
        }
        Button(onClick = onConfirm) {
            Text("Confirm selection")
        }
    }
}

Ten en cuenta lo siguiente en este fragmento:

  • Calendar.getInstance() inicializa TimePickerState con la hora actual.
  • El elemento TimePicker componible muestra el selector de hora y toma timePickerState como parámetro.
  • La implementación incluye dos botones: uno para confirmar la selección y otro para descartar el selector.

Esta implementación se ve de la siguiente manera:

Es un selector de hora de marcado. El usuario puede seleccionar una hora con el dial.
Figura 2: Selector de hora de marcado.

Selector de hora de entrada

En este fragmento, se muestra cómo implementar un selector de hora con estilo de entrada básico.

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

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

    Column {
        TimeInput(
            state = timePickerState,
        )
        Button(onClick = onDismiss) {
            Text("Dismiss picker")
        }
        Button(onClick = onConfirm) {
            Text("Confirm selection")
        }
    }
}

Puntos clave que debes tener en cuenta en esta implementación:

  • La estructura es esencialmente la misma que la del selector de hora de marcado, con la principal diferencia de que se usa TimeInput en lugar de TimePicker.
  • El parámetro is24Hour para timePickerState se establece de forma explícita en true. De forma predeterminada, este valor es false.

Esta implementación se ve de la siguiente manera:

Es un selector de hora de entrada. El usuario puede ingresar una hora con campos de texto.
Figura 3: Es un selector de hora de entrada.

Cómo usar el estado

Para usar el tiempo que el usuario seleccionó en un selector de hora, pasa el TimePickerState adecuado a tu función onConfirm. Luego, el elemento componible principal puede acceder a la hora seleccionada a través de TimePickerState.hour y TimePickerState.minute.

En el siguiente fragmento, se muestra cómo hacerlo:

@Composable
fun DialUseStateExample(
    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,
    )

    Column {
        TimePicker(
            state = timePickerState,
        )
        Button(onClick = onDismiss) {
            Text("Dismiss picker")
        }
        Button(onClick = { onConfirm(timePickerState) }) {
            Text("Confirm selection")
        }
    }
}

Luego, podrías llamar al elemento componible de la siguiente manera:

var selectedTime: TimePickerState? by remember { mutableStateOf(null) }

// ...

DialUseStateExample(
    onDismiss = {
        showDialExample = false
    },
    onConfirm = {
            time ->
        selectedTime = time
        showDialExample = false
    },
)

// ...

if (selectedTime != null) {
    val cal = Calendar.getInstance()
    cal.set(Calendar.HOUR_OF_DAY, selectedTime!!.hour)
    cal.set(Calendar.MINUTE, selectedTime!!.minute)
    cal.isLenient = false
    Text("Selected time = ${formatter.format(cal.time)}")
} else {
    Text("No time selected.")
}

Para obtener más detalles, consulta la implementación completa en la app de fragmentos.

Recursos adicionales