Les sélecteurs de date permettent aux utilisateurs de sélectionner une date, une plage de dates ou les deux. Ils utilisent une boîte de dialogue de calendrier ou une saisie de texte pour permettre aux utilisateurs de sélectionner des dates.
Types
Il existe trois types de sélecteurs de date:
- Ancré: s'affiche en ligne dans la mise en page. Il convient aux mises en page compactes où une boîte de dialogue dédiée peut sembler intrusive.
- Modale: apparaît sous la forme d'une boîte de dialogue superposée au contenu de l'application. Cela permet de se concentrer clairement sur la sélection de la date.
- Entrée modale: combine un champ de texte avec un sélecteur de date modal.
Vous pouvez implémenter ces sélecteurs de date dans votre application à l'aide des composables suivants:
DatePicker
: composable général pour un sélecteur de date. Le conteneur que vous utilisez détermine s'il est ancré ou modèle.DatePickerDialog
: conteneur des sélecteurs de date d'entrée modal et modal.DateRangePicker
: pour tout sélecteur de date dans lequel l'utilisateur peut sélectionner une plage avec une date de début et de fin.
État
Le paramètre clé que les différents composables de sélecteur de date partagent est state
, qui prend un objet DatePickerState
ou DateRangePickerState
. Leurs propriétés capturent des informations sur la sélection de l'utilisateur à l'aide du sélecteur de date, comme la date sélectionnée actuellement.
Pour en savoir plus sur l'utilisation de la date sélectionnée, consultez la section Utiliser la date sélectionnée.
Sélecteur de date ancré
Dans l'exemple suivant, un champ de texte invite l'utilisateur à saisir sa date de naissance. Lorsqu'il clique sur l'icône de calendrier dans le champ, un sélecteur de date intégré s'ouvre sous le champ de saisie.
@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)) }
Points clés concernant le code
- Le sélecteur de date s'affiche lorsque l'utilisateur clique sur
IconButton
.- Le bouton d'icône sert d'argument pour le paramètre
trailingIcon
deOutlinedTextField
. - La variable d'état
showDatePicker
contrôle la visibilité du sélecteur de date ancré.
- Le bouton d'icône sert d'argument pour le paramètre
- Le conteneur du sélecteur de date est un composable
Popup
, qui superpose le contenu sans affecter la mise en page des autres éléments. selectedDate
capture la valeur de la date sélectionnée à partir de l'objetDatePickerState
et la met en forme à l'aide de la fonctionconvertMillisToDate
.- La date sélectionnée s'affiche dans le champ de texte.
- Le sélecteur de date ancré est positionné sous le champ de texte à l'aide d'un modificateur
offset
. - Un
Box
est utilisé comme conteneur racine pour permettre une superposition appropriée du champ de texte et du sélecteur de date.
Résultats
Après avoir cliqué sur l'icône d'agenda, cette implémentation s'affiche comme suit:
Sélecteur de date modal
Un sélecteur de date modal affiche une boîte de dialogue flottante sur l'écran. Pour l'implémenter, créez un DatePickerDialog
et transmettez-lui 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) } }
Points clés concernant le code
- La fonction composable
DatePickerModal
affiche un sélecteur de date modal. - L'expression lambda
onDateSelected
s'exécute lorsque l'utilisateur sélectionne une date.- Il expose la date sélectionnée au composable parent.
- L'expression lambda
onDismiss
s'exécute lorsque l'utilisateur ferme la boîte de dialogue.
Résultats
Cette implémentation est la suivante :
Sélecteur de date modal de saisie
Un sélecteur de date modal avec saisie affiche une boîte de dialogue flottante sur l'écran et permet à l'utilisateur de saisir une date.
@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) } }
Points clés concernant le code
Cette procédure est très semblable à celle de l'exemple de sélecteur de date modal. La principale différence est la suivante:
- Le paramètre
initialDisplayMode
définit le mode d'affichage initial surDisplayMode.Input
.
Sélecteur de date avec plage
Vous pouvez créer un sélecteur de date qui permet à l'utilisateur de sélectionner une plage entre une date de début et une date de fin. Pour ce faire, utilisez DateRangePicker
.
L'utilisation de DateRangePicker
est essentiellement la même que celle de DatePicker
. Vous pouvez l'utiliser pour un sélecteur ancré en tant qu'enfant de PopUp
, ou l'utiliser en tant que sélecteur modal et le transmettre à DatePickerDialog
. La principale différence est que vous utilisez DateRangePickerState
au lieu de DatePickerState
.
L'extrait de code suivant montre comment créer un sélecteur de date modal avec une plage:
@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) ) } }
Points clés concernant le code
- Le paramètre
onDateRangeSelected
est un rappel qui reçoit unPair<Long?, Long?>
représentant les dates de début et de fin sélectionnées. Cela donne au composable parent accès à la plage sélectionnée. rememberDateRangePickerState()
crée l'état du sélecteur de plage de dates.DatePickerDialog
crée un conteneur de boîte de dialogue modale.- Dans le gestionnaire
onClick
du bouton de confirmation,onDateRangeSelected
transmet la plage sélectionnée au composable parent. - Le composable
DateRangePicker
sert de contenu de la boîte de dialogue.
Résultats
Cette implémentation est la suivante :
Utiliser la date sélectionnée
Pour capturer la date sélectionnée, suivez-la dans le composable parent en tant que Long
et transmettez la valeur à DatePicker
dans onDateSelected
. L'extrait de code suivant le montre, mais vous pouvez voir l'implémentation complète dans l'application officielle d'extraits.
// ... 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 } ) } // ...
Il en va essentiellement de même pour les sélecteurs de date de plage, mais vous devez utiliser un Pair<Long?, Long?>
ou une classe de données pour capturer les valeurs de début et de fin.