一、概念
一般是以对话框的形式呼出,DatePickerDialog 就是对 DatePicker 的一个简单对话框封装。
@Composable todayDateBorderColor = Color.Red //默认选中的当天日期的边框色 selectedDayContentColor = Color.Red //选中的文字颜色 selectedDayContainerColor = Color.Red //选中的填充颜色 ) |
@Composable |
输入模式 | 选择模式 |
二、基本使用
2.1 获取状态
2.1.1 单个日期选择 rememberDatePickerState()
@Composable fun rememberDatePickerState( @Suppress("AutoBoxing") initialSelectedDateMillis: Long? = null, //默认选中的日期 @Suppress("AutoBoxing") initialDisplayedMonthMillis: Long? = initialSelectedDateMillis, //默认显示的月份 yearRange: IntRange = DatePickerDefaults.YearRange, //限制选择的年份范围,如 2000..2100 initialDisplayMode: DisplayMode = DisplayMode.Picker //选择模式Picker、输入模式Input ): DatePickerState |
2.1.2 范围日期选择 rememberDateRangePickerState()
@Composable fun rememberDateRangePickerState( @Suppress("AutoBoxing") initialSelectedStartDateMillis: Long? = null, //起始日期 @Suppress("AutoBoxing") initialSelectedEndDateMillis: Long? = null, //结束日期 @Suppress("AutoBoxing") initialDisplayedMonthMillis: Long? = initialSelectedStartDateMillis, //默认显示的月份(如果起始日期没指定就默认是当月) yearRange: IntRange = DatePickerDefaults.YearRange, //允许选择的年份,如 2000..2100 initialDisplayMode: DisplayMode = DisplayMode.Picker //选择模式Picker、输入模式Input ): DateRangePickerState |
2.1.3 自定义可选择日期 selectableDates
Compose Material3 1.2.0-alpha02 及其以上版本,提供了一个 selectableDates 参数,可以在其中完全自定义可以选择的日期。
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().dayOfWeekdayOfWeek != DayOfWeek.SUNDAY && dayOfWeek != DayOfWeek.SATURDAY} else {val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))calendar.timeInMillis = utcTimeMilliscalendar[Calendar.DAY_OF_WEEK] != Calendar.SUNDAY &&calendar[Calendar.DAY_OF_WEEK] != Calendar.SATURDAY}}// 只允许选择2023年以前override fun isSelectableYear(year: Int): Boolean {return year > 2022}})
2.2 DatePicker
val datePickerState = rememberDatePickerState()
DatePicker(state = datePickerState)
Text("当前选中日期的时间戳 ${datePickerState.selectedDateMillis ?: "没有选择"}")
2.3 DatePickerDialog
var isOpenDialog by remember { mutableStateOf(false) }
val datePickerState = rememberDatePickerState()
val sdf = remember { SimpleDateFormat("yyy-MM-dd") }if (isOpenDialog) {DatePickerDialog(onDismissRequest = { isOpenDialog = false},colors = DatePickerDefaults.colors(containerColor = AppColors.White), //背景色(这个在下面的DatePicker中设置无效)confirmButton = {Text(modifier = Modifier.clickableNoRipple {//拿到的是时间戳,需要格式化val date = datePickerState.selectedDateMillisif (date != null) {onValueChange(sdf.format(date))isDefaultValue = false}isOpenDialog = false},text = "确定",)},dismissButton = {Text(modifier = Modifier.clickableNoRipple { isOpenDialog = false },text = "取消")}) {DatePicker(state = datePickerState,colors = DatePickerDefaults.colors(todayDateBorderColor = AppColors.Primary, //默认选中的当天日期的边框色selectedDayContentColor = AppColors.White, //选中的文字颜色selectedDayContainerColor = AppColors.Primary, //选中的填充颜色))}
}
三、封装
3.1 单按钮时间选择对话框
@Preview
@Composable
private fun SingleButtonDatePickerPreView() {var value by remember { mutableStateOf("选择时间") }SingleButtonDatePickerView(value = value,onValueChange = { value = it },)
}@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SingleButtonDatePickerView(modifier: Modifier = Modifier,value: String = "选择时间",onValueChange: (String) -> Unit,borderColor: Color = AppColors.Hint,
) {var isOpenDialog by remember { mutableStateOf(false) }var isDefaultValue by remember { mutableStateOf(true) }val datePickerState = rememberDatePickerState()val sdf = remember { SimpleDateFormat("yyy-MM-dd") }Row(modifier = modifier.height(AppDimens.heightButton).border(width = 1.dp,color = borderColor,shape = RoundedCornerShape(AppDimens.radius)).padding(horizontal = AppDimens.paddingContent).clickableNoRipple { isOpenDialog = true },verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.SpaceBetween) {Text(text = value,maxLines = 1,color = if(isDefaultValue) AppColors.Hint else AppColors.Black,fontSize = AppDimens.textPrimary,)Icon(modifier = Modifier.padding(start = 5.dp),imageVector = Icons.Default.CalendarMonth,contentDescription = null,tint = AppColors.Hint)}if (isOpenDialog) {DatePickerDialog(onDismissRequest = { isOpenDialog = false},colors = DatePickerDefaults.colors(containerColor = AppColors.White), //背景色(这个在下面的DatePicker中设置无效)confirmButton = {Text(modifier = Modifier.clickableNoRipple {val date = datePickerState.selectedDateMillisif (date != null) {onValueChange(sdf.format(date))isDefaultValue = false} else {isDefaultValue = true}isOpenDialog = false}.padding(end = 20.dp),text = "确定",color = AppColors.Primary,fontSize = AppDimens.textTitle)},dismissButton = {Text(modifier = Modifier.clickableNoRipple {isOpenDialog = false}.padding(end = 20.dp),text = "取消",color = AppColors.textGray,fontSize = AppDimens.textTitle)}) {DatePicker(state = datePickerState,colors = DatePickerDefaults.colors(todayDateBorderColor = AppColors.Primary, //默认选中的当天日期的边框色selectedDayContentColor = AppColors.White, //选中的文字颜色selectedDayContainerColor = AppColors.Primary, //选中的填充颜色))}}
}
3.2 双按钮时间选择对话框
@Preview
@Composable
private fun TwoButtonDatePickerPreview() {var startDate by remember { mutableStateOf("开始时间") }var endDate by remember { mutableStateOf("结束时间") }TwoButtonDatePickerView(startDate = startDate,endDate = endDate,onStartChange = { startDate = it },onEndChange = { endDate = it },)
}@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TwoButtonDatePickerView(modifier: Modifier = Modifier,startDate: String = "开始时间",endDate: String = "结束时间",onStartChange: (String) -> Unit,onEndChange: (String) -> Unit,borderColor: Color = AppColors.Hint,
) {var isOpenStartDialog by remember { mutableStateOf(false) }var isOpenEndDialog by remember { mutableStateOf(false) }val startDatePickerState = rememberDatePickerState()val endDatePickerState = rememberDatePickerState()var isStartDateDefault by remember { mutableStateOf(true) }var isEndDateDefault by remember { mutableStateOf(true) }val sdf = remember { SimpleDateFormat("yyy-MM-dd") }Row(modifier = modifier.height(AppDimens.heightButton).border(width = 1.dp,color = borderColor,shape = RoundedCornerShape(AppDimens.radius)).padding(horizontal = AppDimens.paddingContent),verticalAlignment = Alignment.CenterVertically,) {Text(modifier = Modifier.clickableNoRipple { isOpenStartDialog = true },text = startDate,color = if (isStartDateDefault) AppColors.Hint else AppColors.Black,maxLines = 1,fontSize = AppDimens.textPrimary)Icon(modifier = Modifier.size(25.dp).padding(horizontal = 5.dp),painter = painterResource(id = R.drawable.icon_arrow_right),contentDescription = null,tint = AppColors.Hint)Text(modifier = Modifier.clickableNoRipple { isOpenEndDialog = true },text = endDate,color = if (isEndDateDefault) AppColors.Hint else AppColors.Black,maxLines = 1,fontSize = AppDimens.textPrimary)Icon(modifier = Modifier.padding(start = 5.dp),imageVector = Icons.Default.CalendarMonth,contentDescription = null,tint = AppColors.Hint)}if (isOpenStartDialog) {DatePickerDialog(onDismissRequest = { isOpenStartDialog = false},colors = DatePickerDefaults.colors(containerColor = AppColors.White),confirmButton = {Text(modifier = Modifier.clickableNoRipple {val date = startDatePickerState.selectedDateMillisif (date != null) {onStartChange(sdf.format(date))isStartDateDefault = false} else {isStartDateDefault = true}isOpenStartDialog = false}.padding(end = 20.dp),text = "确定",color = AppColors.Primary,fontSize = AppDimens.textTitle)},dismissButton = {Text(modifier = Modifier.clickableNoRipple {isOpenStartDialog = false}.padding(end = 20.dp),text = "取消",color = AppColors.textGray,fontSize = AppDimens.textTitle)}) {DatePicker(state = startDatePickerState,colors = DatePickerDefaults.colors(todayDateBorderColor = AppColors.Primary,selectedDayContentColor = AppColors.White,selectedDayContainerColor = AppColors.Primary,))}}if (isOpenEndDialog) {DatePickerDialog(onDismissRequest = { isOpenEndDialog = false},colors = DatePickerDefaults.colors(containerColor = AppColors.White),confirmButton = {Text(modifier = Modifier.clickableNoRipple {val date = endDatePickerState.selectedDateMillisif (date != null) {onEndChange(sdf.format(date))isEndDateDefault = false} else {isEndDateDefault = true}isOpenEndDialog = false}.padding(end = 20.dp),text = "确定",color = AppColors.Primary,fontSize = AppDimens.textTitle)},dismissButton = {Text(modifier = Modifier.clickableNoRipple {isOpenEndDialog = false}.padding(end = 20.dp),text = "取消",color = AppColors.textGray,fontSize = AppDimens.textTitle)}) {DatePicker(state = endDatePickerState,colors = DatePickerDefaults.colors(containerColor = AppColors.White,todayDateBorderColor = AppColors.Primary,selectedDayContentColor = AppColors.White,selectedDayContainerColor = AppColors.Primary,))}}
}