Selektory dat umożliwiają użytkownikom wybieranie daty, zakresu dat lub obu tych opcji. Umożliwiają one użytkownikom wybieranie dat za pomocą okna kalendarza lub wpisywanie tekstu.
Typy
Istnieją 3 typy selektorów daty:
- Zadokowano: wyświetla się w układzie. Jest to odpowiednie rozwiązanie w przypadku kompaktowych układów, w których dedykowane okno dialogowe może być uciążliwe.
- Modalna: wyświetla się jako okno dialogowe nakładające się na zawartość aplikacji. Ułatwia to wybór daty.
- Modal input (Pole modalne): łączy pole tekstowe z modalnym selektorem daty.
W aplikacji możesz zaimplementować te selektory daty za pomocą tych funkcji kompozycyjnych:
DatePicker
: ogólny komponent do wyboru daty. Kontener, którego używasz, określa, czy jest on zadokowany, czy modelowany.DatePickerDialog
: kontener zarówno dla selektora daty w oknie modalnym, jak i dla selektora daty w oknie modalnym z polem wejściowym.DateRangePicker
: w przypadku dowolnego selektora daty, w którym użytkownik może wybrać zakres z datą rozpoczęcia i zakończenia.
Województwo
Parametrem kluczowym, który jest wspólny dla różnych komponentów do wyboru daty, jest state
, który przyjmuje obiekt DatePickerState
lub DateRangePickerState
. Ich właściwości rejestrują informacje o wyborze użytkownika za pomocą selektora daty, np. aktualnie wybraną datę.
Więcej informacji o tym, jak korzystać z wybranej daty, znajdziesz w sekcji Korzystanie z wybranej daty.
Zadokowany selektor daty
W przykładzie poniżej znajduje się pole tekstowe, w którym użytkownik jest proszony o podanie daty urodzenia. Gdy klikną ikonę kalendarza w polu, poniżej pola wprowadzania otworzy się zadokowany selektor daty.
@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)) }
Najważniejsze informacje o kodzie
- Selektor daty pojawi się, gdy użytkownik kliknie
IconButton
.- Przycisk ikony służy jako argument parametru
OutlinedTextField
trailingIcon
. - Zmienna stanu
showDatePicker
kontroluje widoczność zadokowanego selektora dat.
- Przycisk ikony służy jako argument parametru
- Kontener selektora daty to komponent
Popup
, który nakłada się na treść bez wpływu na układ innych elementów. selectedDate
rejestruje wartość wybranej daty z obiektuDatePickerState
i formatuje ją za pomocą funkcjiconvertMillisToDate
.- Wybrana data pojawi się w polu tekstowym.
- Przykotwiczony selektor dat jest umieszczony pod polem tekstowym za pomocą modyfikatora
offset
. - Element
Box
jest używany jako kontener główny, aby umożliwić prawidłowe ułożenie warstw pola tekstowego i selektora daty.
Wyniki
Po kliknięciu ikony kalendarza implementacja wygląda tak:

Modalny selektor daty
Modalny selektor daty wyświetla okno, które pojawia się na ekranie. Aby go wdrożyć, utwórz DatePickerDialog
i przekaż do niego 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) } }
Najważniejsze informacje o kodzie
- Funkcja typu „composable”
DatePickerModal
wyświetla selektor daty w oknie modalnym. - Wyrażenie lambda
onDateSelected
jest wykonywane, gdy użytkownik wybierze datę.- Przekazuje wybraną datę do elementu kompozycyjnego wyższego rzędu.
- Wyrażenie lambda
onDismiss
jest wykonywane, gdy użytkownik zamyka okno.
Wyniki
Ta implementacja wygląda tak:

Selektor daty w modalnym polu wprowadzania
Modalny selektor dat z polem wprowadzania wyświetla okno, które pojawia się na ekranie i umożliwia użytkownikowi wpisanie daty.
@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) } }
Najważniejsze informacje o kodzie
Jest to bardzo podobne do przykładu selektora dat w oknie modalnym. Podstawowa różnica jest następująca:
- Parametr
initialDisplayMode
ustawia początkowy tryb wyświetlania naDisplayMode.Input
.

Selektor dat z zakresem
Możesz utworzyć selektor daty, który umożliwia użytkownikowi wybranie zakresu między datą początkową a końcową. Aby to zrobić, użyj DateRangePicker
.
Użycie DateRangePicker
jest w zasadzie takie samo jak DatePicker
. Możesz użyć go jako zadokowanego selektora jako elementu podrzędnego PopUp
lub jako modalnego selektora i przekazać go do DatePickerDialog
. Podstawowa różnica polega na tym, że zamiast DatePickerState
używasz operatora DateRangePickerState
.
Poniższy fragment kodu pokazuje, jak utworzyć modalny selektor dat z zakresem:
@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) ) } }
Najważniejsze informacje o kodzie
- Parametr
onDateRangeSelected
to wywołanie zwrotne, które otrzymujePair<Long?, Long?>
reprezentujące wybrane daty rozpoczęcia i zakończenia. Dzięki temu funkcja kompozycyjna nadrzędna ma dostęp do wybranego zakresu. rememberDateRangePickerState()
tworzy stan selektora zakresu dat.- Tag
DatePickerDialog
tworzy kontener okna modalnego. - W obsłudze przycisku potwierdzenia
onClick
funkcjaonDateRangeSelected
przekazuje wybrany zakres do nadrzędnego komponentu. - Element
DateRangePicker
pełni funkcję treści okna.
Wyniki
Ta implementacja wygląda tak:

Użyj wybranej daty
Aby zarejestrować wybraną datę, śledź ją w kompozycji nadrzędnej jako Long
i przekaż wartość do elementu DatePicker
w onDateSelected
. Pokazuje to poniższy fragment kodu, ale pełną implementację możesz zobaczyć w oficjalnej aplikacji z fragmentami kodu.
// ... 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 } ) } // ...
W przypadku selektorów zakresu dat obowiązuje ta sama zasada, ale do przechwytywania wartości początkowej i końcowej musisz użyć Pair<Long?, Long?>
lub klasy danych.