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

news2024/11/28 16:50:48

前言

在之前我使用 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().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
            }
        }
    )

运行效果如下:

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 = false
                    println("选中时间戳为: ${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.coloradmin.cn/o/664448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图书推荐|Python数据分析与挖掘实战(第2版)

Python数据分析与挖掘实战(第2版)一共分为三个部分,包括基础篇(第1~5章)、实战篇(第6~12章)、提高篇(第13章)。其中基础篇介绍了数据挖掘的基本原…

揭秘猫狗的微生物世界:肠道微生物群的意义和影响

谷禾健康 “铲屎官”们都希望自己的宠物有一个健康的身体。但是猫狗都不会说话,平时我们只能从它们的精神状态来判断它们是否健康,但这并不准确。去宠物医院又不太方便,很多猫咪和狗狗还会对抽血等检查有所抗拒。 肠道微生物检测在人类中的应…

边云协同:大小模型如何协同推理?

1 背景 “化繁为简、大巧不工”是机器学习的初衷之一。 费米曾讲述一个故事,冯诺依曼告诉他,用四个参数就可以拟合出一头大象,用五个参数就可以让大象鼻子动起来,这就是“四个参数画大象”的故事。 但AI模型规模不断剧增已是不…

CVE-2023-27524 Apache Superset 身份认证绕过漏洞

漏洞简介 Apache Superset是一个开源的数据可视化和数据探测平台,它基于Python构建,使用了一些类似于Django和Flask的Python web框架。提供了一个用户友好的界面,可以轻松地创建和共享仪表板、查询和可视化数据,也可以集成到其他应…

第一章 string模块

1. string模块介绍 Python中的第三方模块 string 模块解决了一些关于字符串操作的问题。例如,string 模块中可列出所有的大小写英文字母、数字、标点符号、八进制数字字符、十进制数字字符、十六进制数字字符等 Python 中可打印的字符;还可以进行格式化…

学习笔记之MySQL存储引擎

一、MySQL架构 MySQL的连接层处理客户端连接和权限管理,服务层解析和执行SQL语句,引擎层负责数据的存储和检索,存储层处理数据在磁盘上的读写操作。这种架构使得MySQL可以在不同的场景中灵活运行,并根据需求选择合适的存储引擎和…

Spring Security OAuth2.0认证授权 --- 基础篇

一、基本概念 1.1、什么是认证 进入移动互联网时代,大家每天都在刷手机,常用的软件有微信、支付宝、头条等,下边拿微信来举例子说明认证相关的基本概念,在初次使用微信前需要注册成为微信用户,然后输入账号和密码即可…

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…

【yolov5系列】将模型部署到瑞芯微RK3566上面

本篇博客记录将yolov5s移植到瑞芯微3566上的整体流程。当然在其它芯片上的操作类似,差别会在具体的API的调用上。 1 芯片相关 芯片参数:https://www.rock-chips.com/a/cn/product/RK35xilie/2021/0113/1273.htmlCPU:四核,1.8GHZ.N…

CSS查缺补漏之《选择器的复杂用法》

最近在复盘CSS基础知识,发现很多CSS选择器里面还是大有学问,需要详细总结一番,以备差缺补漏~ 作为CSS基础的一大类别,选择器又分为多种类别,本篇内容默认读者已了解并掌握基础选择器【通配符选择器】、【元素选择器】…

企业采用融合CDN战略之前的相关注意事项

很多企业可能都会犹豫是否要从单CDN模式到转向为多CDN模式,一方面因为这可能看起来很复杂,这不仅涉及到需要建立更多的CDN提供商,而且还有其他较多的操作和配置要做,尤其是在当前单CDN供应商似乎一切正常的情况下。但从另一方面来…

【每日算法】【203. 移除链表元素】

☀️博客主页:CSDN博客主页 💨本文由 我是小狼君 原创,首发于 CSDN💢 🔥学习专栏推荐:面试汇总 ❗️游戏框架专栏推荐:游戏实用框架专栏 ⛅️点赞 👍 收藏 ⭐留言 📝&…

《C++高级编程》读书笔记(八、九:类和对象)

1、参考引用 C高级编程(第4版,C17标准)马克葛瑞格尔 2、建议先看《21天学通C》 这本书入门,笔记链接如下 21天学通C读书笔记(文章链接汇总) 1. 编写类 编写类时,需要指定行为或方法 (应用于类的…

8.3 TCP/IP协议与五层体系结构

目录 TCP/IP及五层体系结构 OSI与TCP/IP TCP/IP 的体系结构 沙漏计时器形状的 TCP/IP 协议族 具有五层协议的体系结构 五层协议的体系结构 各层的主要功能 互联网中客户-服务器工作方式 同时为多个客户进程提供服务 TCP/IP及五层体系结构 OSI与TCP/IP TCP/IP 的体系结构 现…

Atcoder Beginner Contest 306

A - Echo AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> using namespace std; int main() {int n;cin>>n;string s;cin>>s;for(int i0;i<n;i){cout<<s[i]<<s[i];}return 0; } B - Base 2 lo…

服务调用OpenFeign

OpenFeign OpenFeign 介绍OpenFeign 的使用OpenFeign 参数传递OpenFeign 超时控制OpenFeign 日志设置OpenFeign 的工作流程 OpenFeign 介绍 Feign 是 SpringCloud组件中一个轻量级RESTful的HTTP服务客户端&#xff0c;Feign集成了Ribbon、RestTemplate 实现了负载均衡的执行Ht…

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

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

Python面向对象编程1-面向过程的简单纸牌游戏程序 项目1.6 完整的猜大小纸牌游戏

总项目目标&#xff1a;用面向过程思想设计一个简单的纸牌游戏程序&#xff0c;称为"Higher or Lower"&#xff08;高还是低&#xff09;。游戏中&#xff0c;玩家需要猜测接下来的一张牌是比当前牌高还是低。根据猜测的准确性&#xff0c;玩家可以得到或失去相应的积…

学了些性能知识,实际工作如何开展性能测试?

目录 前言&#xff1a; 确定需求 了解业务 搭建测试环境 脚本执行及监控 收集测试结果 持续学习 前言&#xff1a; 学到了性能测试的知识&#xff0c;接下来如何在实际工作中开展性能测试呢&#xff1f; 确定需求 刚接触性能测试的同学往往不知道性能测试是有需求的。…

C++右值引用问题

1、右值引用与函数重载 class Int {int value; public:Int(int x 0) :value(x) { cout << "create " << this << endl; }~Int() { cout << "destroy " << this << endl; }Int(const Int& it) :value(it.value){…