Selectores de fechas

Los selectores de fechas permiten que los usuarios seleccionen una fecha, un período o ambas. Usan un un diálogo de calendario o una entrada de texto para permitir que los usuarios seleccionen fechas.

Tipos

Existen tres tipos de selectores de fecha:

  • Anclado: Aparece intercalado en el diseño. Es adecuado para los modelos compacto en los que un diálogo dedicado puede parecer intrusivo.
  • Modal: Aparece como un diálogo que se superpone al contenido de la app. Esto proporciona un un enfoque claro en la selección de fechas.
  • Entrada modal: Combina un campo de texto con un selector de fecha modal.

Puedes implementar estos selectores de fecha en tu app usando lo siguiente: elementos componibles:

  • DatePicker: Elemento componible general para un selector de fecha El contenedor que usar determina si está conectado o si es un modelo.
  • DatePickerDialog: Es el contenedor para la fecha de entrada modal y modal. selectores.
  • DateRangePicker: Para cualquier selector de fecha en el que el usuario puede elegir una período con una fecha de inicio y de finalización.

State

El parámetro clave que comparten los diferentes elementos componibles del selector de fecha es state, que toma un objeto DatePickerState o objeto DateRangePickerState. Sus propiedades capturan información sobre la selección del usuario con el selector de fecha, como la fecha seleccionada actualmente.

Para obtener más información sobre cómo puedes usar la fecha seleccionada, consulta el artículo Cómo usar sección de fecha seleccionada.

Selector de fecha anclado

En el siguiente ejemplo, hay un campo de texto que le solicita al usuario que ingrese su fecha de nacimiento. Cuando hacen clic en el ícono de calendario en el campo, se abre un el selector de fecha conectado debajo del campo de entrada.

@Composable
fun DatePickerDocked() {
    var showDatePicker by remember { mutableStateOf(false) }
    val datePickerState = rememberDatePickerState()
    val selectedDate = datePickerState.selectedDateMillis?.let {
        convertMillisToDate(it)
    } ?: ""

    Box(
        modifier = Modifier.fillMaxWidth()
    ) {
        OutlinedTextField(
            value = selectedDate,
            onValueChange = { },
            label = { Text("DOB") },
            readOnly = true,
            trailingIcon = {
                IconButton(onClick = { showDatePicker = !showDatePicker }) {
                    Icon(
                        imageVector = Icons.Default.DateRange,
                        contentDescription = "Select date"
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .height(64.dp)
        )

        if (showDatePicker) {
            Popup(
                onDismissRequest = { showDatePicker = false },
                alignment = Alignment.TopStart
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .offset(y = 64.dp)
                        .shadow(elevation = 4.dp)
                        .background(MaterialTheme.colorScheme.surface)
                        .padding(16.dp)
                ) {
                    DatePicker(
                        state = datePickerState,
                        showModeToggle = false
                    )
                }
            }
        }
    }
}

fun convertMillisToDate(millis: Long): String {
    val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault())
    return formatter.format(Date(millis))
}

Puntos clave sobre el código

  • El selector de fecha aparece cuando el usuario hace clic en la IconButton.
    • El botón del ícono sirve como argumento del elemento OutlinedTextField. Parámetro trailingIcon.
    • La variable de estado showDatePicker controla la visibilidad de la selector de fecha acoplado.
  • El contenedor del selector de fecha es un elemento Popup componible, que se superpone a la sin afectar el diseño de los demás elementos.
  • selectedDate captura el valor de la fecha seleccionada desde el El objeto DatePickerState y le da formato con convertMillisToDate. .
  • La fecha seleccionada aparecerá en el campo de texto.
  • El selector de fecha anclado se coloca debajo del campo de texto con un offset modificador.
  • Se usa un Box como contenedor raíz para permitir la superposición adecuada del texto. y el selector de fecha.

Resultados

Después de hacer clic en el ícono de calendario, esta implementación aparecerá de la siguiente manera:

Ejemplo del selector de fecha anclado.
Figura 1: Un selector de fecha anclado

Un selector de fecha modal muestra un diálogo que flota en la pantalla. Para implementar crea una DatePickerDialog y pásale una DatePicker.

@Composable
fun DatePickerModal(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

  • La función de componibilidad DatePickerModal muestra un selector de fecha modal.
  • La expresión lambda onDateSelected se ejecuta cuando el usuario selecciona un fecha.
    • Expone la fecha seleccionada en el elemento componible superior.
  • La expresión lambda onDismiss se ejecuta cuando el usuario descarta el .

Resultados

Esta implementación aparece de la siguiente manera:

Ejemplo de selector de fecha modal.
Figura 2: Un selector de fecha modal.

Selector de fecha modal de entrada

Un selector de fecha modal con entrada muestra un diálogo que flota sobre la pantalla y le permite al usuario ingresar una fecha.

@Composable
fun DatePickerModalInput(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

Esto es muy similar al ejemplo del selector de fecha modal. El principal la siguiente es la diferencia:

  • El parámetro initialDisplayMode establece el modo de visualización inicial en DisplayMode.Input
Selector de fecha modal con entrada.
Figura 3: Un selector de fecha modal con entrada

Selector de fecha con período

Puedes crear un selector de fecha que le permita al usuario seleccionar un período entre la fecha de inicio y la fecha de finalización. Para hacerlo, usa DateRangePicker.

El uso de DateRangePicker es, en esencia, el mismo que el de DatePicker. Puedes úsalo para un selector conectado como elemento secundario de PopUp, o bien puedes usarlo como selector modal y pasarlo a DatePickerDialog. La principal diferencia es que uses DateRangePickerState en lugar de DatePickerState.

El siguiente fragmento demuestra cómo crear un selector de fecha modal con una rango:

@Composable
fun DateRangePickerModal(
    onDateRangeSelected: (Pair<Long?, Long?>) -> Unit,
    onDismiss: () -> Unit
) {
    val dateRangePickerState = rememberDateRangePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(
                onClick = {
                    onDateRangeSelected(
                        Pair(
                            dateRangePickerState.selectedStartDateMillis,
                            dateRangePickerState.selectedEndDateMillis
                        )
                    )
                    onDismiss()
                }
            ) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DateRangePicker(
            state = dateRangePickerState,
            title = {
                Text(
                    text = "Select date range"
                )
            },
            showModeToggle = false,
            modifier = Modifier
                .fillMaxWidth()
                .height(500.dp)
                .padding(16.dp)
        )
    }
}

Puntos clave sobre el código

  • El parámetro onDateRangeSelected es una devolución de llamada que recibe un Pair<Long?, Long?>, que representa las fechas de inicio y finalización seleccionadas. Esta le da al elemento componible superior acceso al rango seleccionado.
  • rememberDateRangePickerState() crea el estado del período. selector.
  • DatePickerDialog crea un contenedor de diálogo modal.
  • En el controlador onClick del botón de confirmación, onDateRangeSelected pasa hacia arriba. el rango seleccionado con el elemento superior componible.
  • El elemento DateRangePicker componible funciona como contenido del diálogo.

Resultados

Esta implementación aparece de la siguiente manera:

Ejemplo del selector de fechas de un período modal.
Figura 4: Un selector de fecha modal con un período seleccionado.

Usar la fecha seleccionada

Para capturar la fecha seleccionada, haz un seguimiento en el elemento componible superior como Long. pasa el valor a DatePicker en onDateSelected. El siguiente fragmento lo demuestra, aunque puedes ver la implementación completa en la página aplicación de fragmentos de código.

// ...
    var selectedDate by remember { mutableStateOf<Long?>(null) }
// ...
        if (selectedDate != null) {
            val date = Date(selectedDate!!)
            val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date)
            Text("Selected date: $formattedDate")
        } else {
            Text("No date selected")
        }
// ...
        DatePickerModal(
            onDateSelected = {
                selectedDate = it
                showModal = false
            },
            onDismiss = { showModal = false }
        )
    }
// ...

Lo mismo se aplica a los selectores de fechas, aunque debes usa un Pair<Long?, Long?> o una clase de datos para capturar los valores de inicio y finalización.

Consulta también