בוררי תאריכים מאפשרים למשתמשים לבחור תאריך, טווח תאריכים או את שניהם. הם משתמשים בתיבת דו-שיח של יומן או בהזנת טקסט כדי לאפשר למשתמשים לבחור תאריכים.
סוגים
יש שלושה סוגים של בוררי תאריכים:
- בעגינה: מופיע בתוך שורה בפריסה. הוא מתאים לפריסות קומפקטיות שבהן תיבת דו-שיח ייעודית עשויה להפריע.
- מודל: מודעה שמופיעה כתיבת דו-שיח שמכסה את תוכן האפליקציה. כך אפשר להתמקד בבחירת התאריכים.
- קלט מודלי: שילוב של שדה טקסט עם חלון מודלי לבחירת תאריך.
אפשר להטמיע את בוררי התאריכים האלה באפליקציה באמצעות הרכיבים הניתנים לקישור הבאים:
DatePicker
: רכיב מורכב כללי לבורר תאריכים. המארז שבו אתם משתמשים קובע אם הוא מקובע או מודל.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
מופעל כשהמשתמש בוחר תאריך.- הוא חושף את התאריך שנבחר לרכיב ההורה הניתן לקישור.
- ביטוי הלמה
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
הוא פונקציית קריאה חוזרת שמקבלת את הערךPair<Long?, Long?>
שמייצג את תאריכי ההתחלה והסיום שנבחרו. כך מתקבלת גישה של הורה ליצירת קומפוזיציות לטווח שנבחר. rememberDateRangePickerState()
יוצרת את המצב של בורר טווח התאריכים.- ה-
DatePickerDialog
יוצר מאגר של תיבת דו-שיח מודאלית. - בטיפול
onClick
של לחצן האישור,onDateRangeSelected
מעביר את הטווח שנבחר לרכיב ההורה הניתן לקישור. - הרכיב הניתן לקישור
DateRangePicker
משמש כתוכן של תיבת הדו-שיח.
תוצאות
ההטמעה הזו נראית כך:
שימוש בתאריך שנבחר
כדי לתעד את התאריך שנבחר, עוקבים אחריו ברכיב ההורה הניתן לקישור כ-Long
ומעבירים את הערך ל-DatePicker
ב-onDateSelected
. קטע הקוד הבא מדגים זאת, אבל אפשר לראות את ההטמעה המלאה באפליקציה הרשמית של קטעי הקוד.
// ... 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 } ) } // ...
אותו הדבר רלוונטי לבוררי תאריכים בטווח, אבל צריך להשתמש ב-Pair<Long?, Long?>
או בסוג נתונים כדי לתעד את ערכי ההתחלה והסיום.