تتيح أداة اختيار التاريخ للمستخدمين اختيار تاريخ أو نطاق زمني أو كليهما. وتستخدم هذه التطبيقات مربّع حوار تقويم أو إدخال نص للسماح للمستخدمين باختيار التواريخ.
الأنواع
هناك ثلاثة أنواع من أدوات اختيار التاريخ:
- مثبَّت على قاعدة الإرساء: يظهر مضمّنًا في التنسيق. وهي مناسبة للتصاميم المكثّفة التي قد يبدو فيها مربّع الحوار المخصّص مزعِجًا.
- النوافذ المنبثقة: تظهر كحوار يطغى على محتوى التطبيق. ويساعد ذلك في تركيز انتباهك على اختيار التاريخ.
- إدخال مشروط: يجمع بين حقل نصي ومنتقي تاريخ مشروط.
يمكنك تنفيذ أدوات اختيار التاريخ هذه في تطبيقك باستخدام العناصر التالية المركّبة:
-
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
.- يعمل زر الرمز كوسيطة لمَعلمة
OutlinedTextField
'strailingIcon
. - تتحكّم متغيّر الحالة
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
أداة اختيار تاريخ في وضع النافذة المنبثقة. - يتم تنفيذ تعبير lambda
onDateSelected
عندما يختار المستخدِم تاريخًا.- ويعرِض التاريخ المحدّد للعنصر الرئيسي القابل للتجميع.
- يتم تنفيذ تعبير lambda
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?>
أو فئة بيانات لتسجيل قيم البدء والانتهاء.