foreword
When I used Comose to write APP before, the official solution for DatePicker has not been given yet.
At that time, in order to implement DatePicker in Compose, there were roughly two options:
One is to use the DatePicker of the original VIew, but because I feel that I have used Compose, and then use VIew, it always feels weird, so I didn't use this solution.
The second is to use a third-party DatePicker written by others. This is the solution I used at the time.
But after searching around, I only found a relatively easy-to-use library. However, this library is written by a French person, so the support for Chinese is not very good. As for this is not very good, what does it mean? You can see it by looking at the picture:
Hahaha, the abbreviation of the week is "star".
Regarding this problem, I also mentioned ISSUE, and explained the source of the problem and the solution in detail, but the author ignored me and has not fixed the problem until today.
As for why I don't mention PR after I fix it myself, see one of the replies:
I’m thinking about ability to inject the functionality from outside if necessary. Default function would be getDisplayName() but it can be overriden by the code similar to the one here. It’s obviously a bug in the Android implementation, so it shouldn’t be fixed by this library.
So the question is put on hold.
Until recently, when I looked through the Compose update log, I found that Compose Material3 1.1.0
starting from the version, three new components have been added DatePicker
DateRangePicker
DatePickerDialog
.
Finally, the official release date has been chosen, so I have to learn from it.
basic usage
First, is the most basic DatePicker
usage.
DatePicker
There is only one required parameter state
, which is used to set some configuration information and get the currently selected date.
We can rememberDatePickerState
generate DatePicker
what we need by state
:
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
val datePickerState = rememberDatePickerState()
DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))
Text("当前选中日期的时间戳 ${
datePickerState.selectedDateMillis ?: "没有选择"}")
}
The effect is as follows:
In this selection page, it is supported to switch to manual input mode by clicking the edit icon next to the date:
Of course, we can also rememberDatePickerState
specify whether to initialize the date selection interface or the input box interface by setting the parameters:
val datePickerState = rememberDatePickerState(
initialDisplayMode = DisplayMode.Picker // 默认显示选择框
// initialDisplayMode = DisplayMode.Input // 默认显示输入框
)
In addition, we can also set the month displayed by default and the year that can only be selected:
val datePickerState = rememberDatePickerState(
yearRange = 2023..2024,
initialDisplayedMonthMillis = 1685577600000 // 注意这里是时间戳
)
If you want to limit the dates that can be selected more freely, you need to use Compose Material3 1.2.0-alpha02
and above versions.
In this version, a parameter called is provided selectableDates
, in which you can completely customize the dates that can be selected. Here is an example of the official sample. If we want to restrict the selection of weekends and only select dates after 2023, then we can do this Write:
val datePickerState = rememberDatePickerState(
selectableDates = object : SelectableDates {
// 禁止选择周末(周六和周日)
override fun isSelectableDate(utcTimeMillis: Long): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val dayOfWeek = Instant.ofEpochMilli(utcTimeMillis).atZone(ZoneId.of("UTC"))
.toLocalDate().dayOfWeek
dayOfWeek != DayOfWeek.SUNDAY && dayOfWeek != DayOfWeek.SATURDAY
} else {
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
calendar.timeInMillis = utcTimeMillis
calendar[Calendar.DAY_OF_WEEK] != Calendar.SUNDAY &&
calendar[Calendar.DAY_OF_WEEK] != Calendar.SATURDAY
}
}
// 只允许选择2023年以前
override fun isSelectableYear(year: Int): Boolean {
return year > 2022
}
}
)
The running effect is as follows:
You can see that weekends are grayed out and cannot be selected.
When clicking to select a year, you cannot choose before 2023:
In the dialog use
The above section is only about basic use, but in the actual development process, there may be more scenarios for selecting dates in Dialog.
So the official also provides a DatePickerDialog
component.
In fact, DatePickerDialog
you can see from the source code that it is simply encapsulated AlertDialog
:
So in fact, there is basically no difference between using and DatePicker
, except that the status of the dialog needs to be additionally processed. Here is still the official sample as an example:
val openDialog = remember {
mutableStateOf(true) }
if (openDialog.value) {
val datePickerState = rememberDatePickerState()
val confirmEnabled = derivedStateOf {
datePickerState.selectedDateMillis != null }
DatePickerDialog(
onDismissRequest = {
openDialog.value = false
},
confirmButton = {
TextButton(
onClick = {
openDialog.value = false
println("选中时间戳为: ${
datePickerState.selectedDateMillis}")
},
enabled = confirmEnabled.value
) {
Text("确定")
}
},
dismissButton = {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("取消")
}
}
) {
DatePicker(state = datePickerState)
}
}
The running effect is as follows:
date range selection
In addition, a function that can select a date range is also provided in the new MD3 API DateRangePicker
.
Its parameters are DatePicker
similar to , except state
changed to DateRangePickerState
.
We can rememberDateRangePickerState
generate one via state
.
In state
, we can set the initial display mode of the time picker ( initialDisplayMode
), the default start date ( initialSelectedStartDateMillis
), the default end date ( initialSelectedEndDateMillis
), the default display date ( initialDisplayedMonthMillis
), and the year allowed to be selected ( yearRange
).
And, likewise, Compose Material3 1.2.0-alpha02
fully customizable dates can be selected on and above selectableDates
.
The display effect of this function is as follows:
val state = rememberDateRangePickerState()
DateRangePicker(state = state, modifier = Modifier.fillMaxSize())
Get the selected value is still through sate
:
println("选择的时间戳范围: ${
state.selectedStartDateMillis}..${
state.selectedEndDateMillis}")
Summarize
This article only briefly introduces the basic usage of date selection in Compsoe Material3, and more usage methods need to be explored by readers themselves.
It can be seen that there are more and more official components of Compose, and they are becoming more and more mature.
Compared with the state when the official version was just released, there was nothing and everything needed to be made by yourself, now it has almost covered all kinds of controls and requirements that we commonly use in development.