انتخابگرهای تاریخ به کاربران امکان میدهند تاریخ، محدوده تاریخ، یا هر دو را انتخاب کنند. آنها از کادر گفتگوی تقویم یا ورودی نوشتار استفاده میکنند تا به کاربران امکان دهند تاریخها را انتخاب کنند.
انواع
سه نوع انتخابگر تاریخ وجود دارد:
- روی پایه اتصال: بهصورت درونخطی در چیدمان ظاهر میشود. برای چیدمانهای فشرده که در آنها کادر گفتگوی اختصاصی ممکن است مزاحم بهنظر برسد مناسب است.
- مشروط: بهعنوان کادر گفتگویی که روی محتوای برنامه قرار میگیرد ظاهر میشود. این کار تمرکز واضحی بر انتخاب تاریخ ایجاد میکند.
- ورودی مشروط: فیلد نوشتاری را با انتخابگر تاریخ مشروط ترکیب میکند.
بااستفاده از عناصر ترکیبی زیر میتوانید این انتخابگرهای تاریخ را در برنامهتان پیادهسازی کنید:
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کلیک میکند، انتخابگر تاریخ ظاهر میشود.- دکمه نماد بهعنوان آرگومان برای پارامتر
OutlinedTextFieldtrailingIconعمل میکند. - متغیر وضعیت
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 منتقل کنید. تفاوت اصلی این است که
بهجای DatePickerState از DateRangePickerState استفاده میکنید.
تکهکد زیر نحوه ایجاد انتخابگر تاریخ مشروط با محدوده را نشان میدهد:
@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?> یا کلاس داده برای گرفتن مقادیر شروع و پایان استفاده کنید.