I selettori della data consentono agli utenti di selezionare una data, un intervallo di date o entrambi. Utilizzano una finestra di dialogo del calendario o un input di testo per consentire agli utenti di selezionare le date.
Tipi
Esistono tre tipi di selettori della data:
- Agganciato: viene visualizzato in linea all'interno del layout. È adatto per layout compatti in cui una finestra di dialogo dedicata potrebbe risultare invasiva.
- Modale: viene visualizzato come una finestra di dialogo che si sovrappone ai contenuti dell'app. In questo modo, l'attenzione si concentra sulla selezione della data.
- Input modale: combina un campo di testo con un selettore della data modale.
Puoi implementare questi selettori della data nella tua app utilizzando i seguenti composabili:
DatePicker: composable generale per un selettore della data. Il container che utilizzi determina se è ancorato o modale.DatePickerDialog: il contenitore per i selettori della data modali e di input modali.DateRangePicker: per qualsiasi selettore della data in cui l'utente può selezionare un intervallo con una data di inizio e una di fine.
Stato
Il parametro chiave che i diversi componibili del selettore della data hanno in comune è state, che accetta un oggetto DatePickerState o DateRangePickerState. Le loro proprietà acquisiscono informazioni sulla selezione dell'utente utilizzando il selettore della data, ad esempio la data attualmente selezionata.
Per saperne di più su come utilizzare la data selezionata, consulta la sezione Utilizza la data selezionata.
Selettore della data ancorato
Nell'esempio seguente, è presente un campo di testo che chiede all'utente di inserire la propria data di nascita. Quando l'utente fa clic sull'icona del calendario nel campo, si apre un selettore della data ancorato sotto il campo di immissione.
@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 ) } } } } } @Composable fun DatePickerFieldToModal(modifier: Modifier = Modifier) { var selectedDate by remember { mutableStateOf<Long?>(null) } var showModal by remember { mutableStateOf(false) } OutlinedTextField( value = selectedDate?.let { convertMillisToDate(it) } ?: "", onValueChange = { }, label = { Text("DOB") }, placeholder = { Text("MM/DD/YYYY") }, trailingIcon = { Icon(Icons.Default.DateRange, contentDescription = "Select date") }, modifier = modifier .fillMaxWidth() .pointerInput(selectedDate) { awaitEachGesture { // Modifier.clickable doesn't work for text fields, so we use Modifier.pointerInput // in the Initial pass to observe events before the text field consumes them // in the Main pass. awaitFirstDown(pass = PointerEventPass.Initial) val upEvent = waitForUpOrCancellation(pass = PointerEventPass.Initial) if (upEvent != null) { showModal = true } } } ) if (showModal) { DatePickerModal( onDateSelected = { selectedDate = it }, onDismiss = { showModal = false } ) } } fun convertMillisToDate(millis: Long): String { val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()) return formatter.format(Date(millis)) }
Punti chiave sul codice
- Il selettore della data viene visualizzato quando l'utente fa clic su
IconButton.- Il pulsante icona funge da argomento per il parametro
trailingIcondiOutlinedTextField. - La variabile di stato
showDatePickercontrolla la visibilità del selettore della data ancorato.
- Il pulsante icona funge da argomento per il parametro
- Il container del selettore della data è un composable
Popup, che si sovrappone ai contenuti senza influire sul layout di altri elementi. selectedDateacquisisce il valore della data selezionata dall'oggettoDatePickerStatee lo formatta utilizzando la funzioneconvertMillisToDate.- La data selezionata viene visualizzata nel campo di testo.
- Il selettore della data ancorato è posizionato sotto il campo di testo utilizzando un modificatore
offset. - Un
Boxviene utilizzato come contenitore principale per consentire la corretta stratificazione del campo di testo e del selettore della data.
Risultati
Dopo aver fatto clic sull'icona del calendario, l'implementazione appare come segue:
Selettore della data modale
Un selettore della data modale mostra una finestra di dialogo che fluttua sullo schermo. Per implementarlo, crea un DatePickerDialog e passagli un 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) } }
Punti chiave sul codice
- La funzione componibile
DatePickerModalmostra un selettore della data modale. - L'espressione lambda
onDateSelectedviene eseguita quando l'utente seleziona una data.- Espone la data selezionata al composable principale.
- L'espressione lambda
onDismissviene eseguita quando l'utente chiude la finestra di dialogo.
Risultati
Ecco come appare la barra:
Selettore della data modale di input
Un selettore della data modale con input mostra una finestra di dialogo che si sovrappone allo schermo e consente all'utente di inserire una data.
@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) } }
Punti chiave sul codice
Questo è molto simile all'esempio di selettore della data modale. La differenza principale è la seguente:
- Il parametro
initialDisplayModeimposta la modalità di visualizzazione iniziale suDisplayMode.Input.
Selettore della data con intervallo
Puoi creare un selettore della data che consenta all'utente di selezionare un intervallo tra una data di inizio e una di fine. Per farlo, utilizza DateRangePicker.
L'utilizzo di DateRangePicker è essenzialmente lo stesso di DatePicker. Puoi
utilizzarlo per un selettore ancorato come elemento secondario di PopUp oppure puoi utilizzarlo come
selettore modale e passarlo a DatePickerDialog. La differenza principale è che utilizzi DateRangePickerState anziché DatePickerState.
Il seguente snippet mostra come creare un selettore della data modale con un intervallo:
@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) ) } }
Punti chiave sul codice
- Il parametro
onDateRangeSelectedè un callback che riceve unPair<Long?, Long?>che rappresenta le date di inizio e di fine selezionate. In questo modo, il composable principale può accedere all'intervallo selezionato. rememberDateRangePickerState()crea lo stato per il selettore dell'intervallo di date.DatePickerDialogcrea un container di finestre di dialogo modali.- Nel gestore
onClickdel pulsante di conferma,onDateRangeSelectedpassa l'intervallo selezionato al composable principale. - Il componibile
DateRangePickerfunge da contenuto della finestra di dialogo.
Risultati
Ecco come appare la barra:
Utilizza la data selezionata
Per acquisire la data selezionata, monitorala nel composable principale come Long e passa il valore a DatePicker in onDateSelected. Lo snippet seguente lo dimostra, anche se puoi vedere l'implementazione completa nell'app di snippet ufficiale.
// ... var selectedDate by remember { mutableStateOf<Long?>(null) } // ... if (selectedDate != null) { val date = Date(selectedDate!!) val formattedDate = SimpleDateFormat("MMM dd, yyyy", LocalLocale.current.platformLocale).format(date) Text("Selected date: $formattedDate") } else { Text("No date selected") } // ... DatePickerModal( onDateSelected = { selectedDate = it showModal = false }, onDismiss = { showModal = false } ) } // ...
In sostanza, lo stesso vale per i selettori della data dell'intervallo, anche se devi utilizzare un Pair<Long?, Long?> o una classe di dati per acquisire i valori di inizio e fine.