Jetpack Compose Material3 组件之 DatePicker(日期选择)

news/2024/11/16 3:33:47/

前言

在之前我使用 Comose 写 APP 的时候,官方还没有给出关于 DatePicker 的解决方案。

当时为了在 Compose 中实现 DatePicker ,大致有两种方案:

一是使用原生 VIew 的 DatePicker,但是因为觉得我即然都用 Compose 了,再去用 VIew ,总觉得怪怪的,所以就没有用这个方案。

二是使用别人写的第三方 DatePicker,我当时采用的就是这个方案。

但是找了一圈,只找到一个相对好用的库,然而这个库是个法国人写,所以对中文的支持不是太好,至于这个不是太好,是什么意思呢?你们看图就知道了:

1.jpg

哈哈哈,星期的缩写都是 “星”。

关于这个问题,我也提了 ISSUE,并且详细解释了问题来源以及解决方法,但是作者并没有理我,直至今日都没有修复这个问题。

至于我为什么不自己修复之后提 PR,看其中一个回复:

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.

所以这个问题就这么搁置了。

直到最近,我翻阅 Compose 更新日志时,发现从 Compose Material3 1.1.0 版本开始,新增了 DatePicker DateRangePicker DatePickerDialog 三个组件。

终于,官方出日期选择了,这不得来学学。

基本用法

首先,是最基本的 DatePicker 的使用。

DatePicker 只有一个必须参数 state,用于设置一些配置信息以及获取当前选中的日期。

我们可以通过 rememberDatePickerState 生成 DatePicker 需要的 state

Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {val datePickerState = rememberDatePickerState()DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))Text("当前选中日期的时间戳 ${datePickerState.selectedDateMillis ?: "没有选择"}")
}

效果如下:

2.png

在这个选择页面中,支持通过点击日期旁边的编辑图标切换至手动输入模式:

3.png
当然,我们也可以通过设置 rememberDatePickerState 的参数来指定初始化显示日期选择界面还是输入框界面:

val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Picker // 默认显示选择框// initialDisplayMode = DisplayMode.Input // 默认显示输入框
)

另外,我们也可以设置默认展示的月份和限制只能选择的年份:

val datePickerState = rememberDatePickerState(yearRange = 2023..2024,initialDisplayedMonthMillis = 1685577600000 // 注意这里是时间戳
)

如果想要更加自由的限制可以选择的日期,则需要使用 Compose Material3 1.2.0-alpha02 及其以上版本。

在这个版本中提供了一个叫 selectableDates 的参数,可以在其中完全自定义可以选择的日期,这里以官方的 sample 举例,如果我们想限制禁止选择周末,且只能选择2023年以后的日期,那么可以这样写:

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}})

运行效果如下:

4.png

可以看到周末是灰色的,不可选中。

点开选择年份时,2023 年以前不可选择:

5.png

在对话框中使用

上面一节讲的只是基本的使用,但是实际开发过程中,或许还是在 Dialog 中选择日期的场景更多。

所以官方也提供了一个 DatePickerDialog 组件。

其实看 DatePickerDialog 的源码就能看出,它也只是简单封装了一下 AlertDialog:

6.png

所以实际上使用和 DatePicker 基本没有区别,只是需要额外处理 dialog 的状态,这里依旧以官方 sample 为例:

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 = falseprintln("选中时间戳为: ${datePickerState.selectedDateMillis}")},enabled = confirmEnabled.value) {Text("确定")}},dismissButton = {TextButton(onClick = {openDialog.value = false}) {Text("取消")}}) {DatePicker(state = datePickerState)}
}

运行效果如下:

7.png

日期范围选择

除此之外,在 MD3 新的 API 中还提供了一个可以选择日期范围的函数 DateRangePicker

它的参数与 DatePicker 类似,只是 state 变为了 DateRangePickerState

我们可以通过 rememberDateRangePickerState 生成一个 state

state 中,我们可以设置时间选择器的初始化展示模式(initialDisplayMode)、默认起始日期(initialSelectedStartDateMillis)、默认结束日期(initialSelectedEndDateMillis)、默认展示日期(initialDisplayedMonthMillis)、允许选择的年份(yearRange)。

并且,同样的,在 Compose Material3 1.2.0-alpha02 及其以上版本还支持完全自定义可以选择的日期 selectableDates

该函数的显示效果如下:

val state = rememberDateRangePickerState()
DateRangePicker(state = state, modifier = Modifier.fillMaxSize())

8.png

获取选中的值依旧是通过 sate:

println("选择的时间戳范围: ${state.selectedStartDateMillis}..${state.selectedEndDateMillis}")

总结

本文只是简要介绍了关于 Compsoe Material3 中关于日期选择的基本使用方法,更多的使用方法还需要读者自行探索。

可以看到,Compose 的官方组件已经越来越多,越来越趋向于成熟。

相较于正式版刚发布没多久时的什么东西都没有,什么都需要自己造轮子的状态,现在几乎已经涵盖了我们开发中常用到的各种控件和需求了。


http://www.ppmy.cn/news/470625.html

相关文章

拉普拉斯方程解决有介质导体球壳问题

一个内径和外径分别为和的导体球壳,带电荷,同心地包围着一个的导体球,使这个导体球接地,求空间各点的电势和这个导体球的感应电荷 我们不难发现,球对称性非常强,电势只和半径有关系 所以我们可以假设电势为…

CVPR2022 多目标跟踪(MOT)汇总-补充篇

为该文章的后续补充https://blog.csdn.net/qq_34919792/article/details/124343166 七、《Multi-Object Tracking Meets Moving UAV》 作者: Shuai Liu†1, Xin Li†2, Huchuan Lu1,2, You He∗3 1Dalian University of Technology, 2Peng Cheng Laboratory, 3Naval Aeronaut…

家用洗地机好用吗?值得推荐的家用洗地机

谁说家务苦差事?现在有了洗地机,家庭清洁变得更加简单、快捷、干净,让您轻松应对家庭日常清洁的要求。洗地机采用先进的技术,自动感应地面脏污,智能调节出水量和吸力,不仅能够保持地面清洁,更能…

软考高级系统架构设计师(二) 基础知识之计算机组成与系统结构

目录 概要 计算机组成结构 CPU组成 冯诺依曼结构 存储系统-层次化存储结构 高速缓冲存储器cache 主存编址计算 磁盘管理 磁盘管理算法 先来先服务(FCFS): 最短寻道时间优先(SSTF) 扫描算法(电梯调度…

性能测试需求分析和学习

在实际的工作中系统的性能需求通常是一个笼统的需求,而且有可能给提需求的人并不知道具体的性能需要,所以只能含糊的列出。如果测试人员不搞清楚,就会出现实际要把杀猪刀,需求标明能屠龙!!! 下…

基于webpack开发react-cli

在前面的章节中我们学习了webpack的基础配置(五大核心属性),以及一些高级优化配置(source map、Tree Shaking、 HMR、Code Split等),并且分别开发了webpack.dev.js(开发环境配置),和webpack.pro…

代码随想录二刷 617. 合并二叉树654. 最大二叉树

617. 合并二叉树 代码如下 func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode { if root1 nil { return root2 } if root2 nil { return root1 } root1.Val root2.Val 用前序遍历将root2的值和root1相加 root1.Left mergeTrees(root1.Left,root2.Left) …

用Python爬取了《扫黑风暴》数据,并将其可视化分析后,终于知道它为什么这么火了~...

今天来跟大家分享一下从数据可视化角度看扫黑风暴~ 绪论如何查找视频id项目结构制作词云图制作最近评论数条形图与折线图制作每小时评论条形图与折线图制作最近评论数饼图制作每小时评论饼图制作观看时间区间评论统计饼图制作扫黑风暴主演提及占比饼图制作评论内容情感分析图评…