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