חלוניות לבחירת תאריך מאפשרות למשתמשים לבחור תאריך, טווח תאריכים או את שניהם. הם משתמשים בתיבת דו-שיח של לוח שנה או בשדה להזנת טקסט כדי לאפשר למשתמשים לבחור תאריכים.
סוגים
יש שלושה סוגים של חלוניות לבחירת תאריך:
- מעוגן: מופיע בתוך השורה בפריסה. הוא מתאים לפריסות קומפקטיות שבהן תיבת דו-שיח ייעודית עלולה להפריע.
- מודאלי: מופיע כתיבת דו-שיח מעל התוכן של האפליקציה. כך המשתמשים יכולים להתמקד בבחירת התאריך.
- קלט מודאלי: שילוב של שדה טקסט עם חלונית מודאלית לבחירת תאריך.
כדי להטמיע את החלוניות האלה לבחירת תאריך באפליקציה, אפשר להשתמש ברכיבים הבאים:
-
DatePicker: פונקציה כללית של Composable לחלונית לבחירת תאריך. המאגר שבו משתמשים קובע אם הוא מעוגן או מודל. -
DatePickerDialog: הקונטיינר של החלונית לבחירת תאריך ושל החלונית להזנת תאריך. -
DateRangePicker: לכל חלונית לבחירת תאריך שבה המשתמש יכול לבחור טווח עם תאריך התחלה ותאריך סיום.
מדינה
הפרמטר העיקרי שמשותף לרכיבים השונים של חלונית לבחירת תאריך הוא state, שמקבל אובייקט DatePickerState או DateRangePickerState. המאפיינים שלהם מתעדים מידע על הבחירה של המשתמש באמצעות החלונית לבחירת תאריך, כמו התאריך שנבחר כרגע.
בקטע שימוש בתאריך שנבחר מוסבר איך להשתמש בתאריך שנבחר.
חלונית מעוגנת לבחירת תאריך
בדוגמה הבאה, יש שדה טקסט שמבקש מהמשתמש להזין את תאריך הלידה שלו. כשהם לוחצים על סמל היומן בשדה, נפתחת חלונית לבחירת תאריך מתחת לשדה להזנת קלט.
@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)) }
מידע חשוב על הקוד
- החלונית לבחירת תאריך מופיעה כשהמשתמש לוחץ על
IconButton.- כפתור הסמל משמש כארגומנט לפרמטר
trailingIconשלOutlinedTextField. - משתנה המצב
showDatePickerקובע אם החלונית לבחירת תאריך תופיע או לא.
- כפתור הסמל משמש כארגומנט לפרמטר
- הקונטיינר של החלונית לבחירת תאריך הוא רכיב קומפוזבילי מסוג
Popup, שמופיע כשכבת-על מעל התוכן בלי להשפיע על הפריסה של רכיבים אחרים. -
selectedDateמתעד את הערך של התאריך שנבחר מהאובייקטDatePickerStateומעצב אותו באמצעות הפונקציהconvertMillisToDate. - התאריך שנבחר מופיע בשדה הטקסט.
- החלונית המעוגנת לבחירת תאריך ממוקמת מתחת לשדה הטקסט באמצעות משתנה מסוג
offset. -
Boxמשמש כמאגר הבסיס כדי לאפשר שכבות מתאימות של שדה הטקסט והחלונית לבחירת תאריך.
תוצאות
אחרי שלוחצים על סמל היומן, ההטמעה הזו נראית כך:
חלונית לבחירת תאריך
במודל של חלונית לבחירת תאריך מוצגת תיבת דו-שיח שצפה מעל המסך. כדי להטמיע אותו, יוצרים DatePickerDialog ומעבירים אליו 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) } }
מידע חשוב על הקוד
- הפונקציה הקומפוזבילית
DatePickerModalמציגה חלונית לבחירת תאריך. - ביטוי הלמבדה
onDateSelectedמופעל כשהמשתמש בוחר תאריך.- הוא חושף את התאריך שנבחר לרכיב ה-Composable ההורה.
- ביטוי הלמבדה
onDismissמופעל כשהמשתמש סוגר את תיבת הדו-שיח.
תוצאות
ההטמעה הזו נראית כך:
חלונית לבחירת תאריך עם קלט
חלונית מודאלית לבחירת תאריך עם קלט מציגה תיבת דו-שיח שצפה מעל המסך ומאפשרת למשתמש להזין תאריך.
@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) } }
מידע חשוב על הקוד
הדוגמה הזו דומה מאוד לדוגמה של חלונית מודאלית לבחירת תאריך. ההבדל העיקרי הוא:
- הפרמטר
initialDisplayModeמגדיר את מצב התצוגה הראשוני ל-DisplayMode.Input.
חלונית לבחירת טווח תאריכים
אתם יכולים ליצור חלונית לבחירת תאריך שמאפשרת למשתמש לבחור טווח בין תאריך התחלה לתאריך סיום. כדי להריץ את הבדיקות האלה, אפשר להשתמש בפקודה DateRangePicker.
השימוש ב-DateRangePicker זהה במהותו לשימוש ב-DatePicker. אפשר להשתמש בו בשביל כלי בחירה מעוגן כצאצא של PopUp, או להשתמש בו ככלי בחירה מודאלי ולהעביר אותו אל DatePickerDialog. ההבדל העיקרי הוא שמשתמשים ב-DateRangePickerState במקום ב-DatePickerState.
בקטע הקוד הבא אפשר לראות איך יוצרים חלונית מודאלית לבחירת טווח תאריכים:
@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) ) } }
מידע חשוב על הקוד
- הפרמטר
onDateRangeSelectedהוא קריאה חוזרת (callback) שמקבלתPair<Long?, Long?>שמייצג את תאריכי ההתחלה והסיום שנבחרו. כך, לרכיב ה-composable הראשי יש גישה לטווח שנבחר. -
rememberDateRangePickerState()יוצר את המצב של בורר טווח התאריכים. - התג
DatePickerDialogיוצר מאגר של תיבת דו-שיח מודאלית. - ב-handler של
onClickבכפתור האישור,onDateRangeSelectedמעביר את הטווח שנבחר לרכיב הקומפוזבילי הראשי. - הפונקציה הקומפוזבילית
DateRangePickerמשמשת כתוכן של תיבת הדו-שיח.
תוצאות
ההטמעה הזו נראית כך:
שימוש בתאריך שנבחר
כדי לתעד את התאריך שנבחר, עוקבים אחריו ב-composable הראשי בתור Long ומעבירים את הערך אל DatePicker ב-onDateSelected. קטע הקוד הבא מדגים את זה, אבל אפשר לראות את ההטמעה המלאה באפליקציית קטעי הקוד הרשמית.
// ... 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 } ) } // ...
אותו עיקרון חל על חלוניות לבחירת טווח תאריכים, אבל צריך להשתמש ב-Pair<Long?, Long?> או במחלקת נתונים כדי לתעד את ערכי ההתחלה והסיום.