
UI组件移动开发【免费下载链接】material-dialogs A beautiful, fluid, and extensible dialogs API for Kotlin Android.项目地址https://gitcode.com/gh_mirrors/ma/material-dialogs点击查看免费下载导读本文围绕开源库material-dialogs的datetime扩展模块展开系统讲解如何在 Kotlin Android 应用中通过声明式 DSL 快速集成**日期选择器Date Picker、时间选择器Time Picker与日期时间选择器DateTime Picker**三种对话框。读完本文你将掌握datePicker、timePicker、dateTimePicker三个扩展函数的全部参数语义、回调用法、结果读取方式并结合源码理解其底层的视图组装、日期校验与“仅限未来时间”约束的实现原理能够直接将其应用到自己的业务表单与筛选场景中。依赖引入与模块定位datetime是 material-dialogs 仓库中的独立子模块位于 datetime/ 目录官方定位是“包含日期、时间、日期时间选择器对话框扩展”的模块。它基于仓库核心模块core的MaterialDialog构建通过 Kotlin 扩展函数的方式把三个 Picker 能力注入到对话框 DSL 中因此在添加依赖时必须同时引入核心模块。以 Maven Central 上当前仓库指定的版本3.2.1为例在build.gradle中添加依赖dependencies { // 核心模块MaterialDialog 本体 implementation com.afollestad.material-dialogs:core:3.2.1 // 日期时间扩展模块 implementation com.afollestad.material-dialogs:datetime:3.2.1 }版本号以你项目实际解析到的依赖为准本文示例统一采用仓库文档中标注的3.2.1。从源码结构看该模块的公开 API 全部集中在三个 Kotlin 文件中DatePickerExt.kt日期选择器扩展TimePickerExt.kt时间选择器扩展DateTimePickerExt.kt日期时间选择器扩展同时定义了共用回调类型DateTimeCallback。三者均以fun MaterialDialog.xxxPicker(...)的形式扩展MaterialDialog遵循 material-dialogs 一贯的show { }声明式风格。日期选择器datePicker基础用法在MaterialDialog(this).show { ... }的对话框配置块内直接调用datePicker即可MaterialDialog(this).show { // 其他对话框配置标题、按钮等 datePicker { dialog, date - // date 为选中的日期类型为 java.util.Calendar } }用户点击“确定”后回调会收到两个参数第一个是对话框实例dialog第二个是选中日期dateCalendar类型可在回调中直接读取年、月、日字段。完整参数说明datePicker的完整签名以源码 DatePickerExt.kt 为准fun MaterialDialog.datePicker( minDate: Calendar? null, maxDate: Calendar? null, currentDate: Calendar? null, requireFutureDate: Boolean false, dateCallback: DateTimeCallback null ): MaterialDialog参数类型默认值作用minDateCalendar?null可选的最早日期早于该日期的日子不可选maxDateCalendar?null可选的最晚日期晚于该日期的日子不可选currentDateCalendar?null初始化时选中的日期日历默认显示今天requireFutureDateBooleanfalse为true时强制只允许选择未来日期否则“确定”按钮禁用dateCallbackDateTimeCallbacknull点击确定后的结果回调参数校验与调用链从源码可以看到datePicker内部首先通过customView加载布局 md_datetime_picker_date.xml该布局的核心是一个自定义com.afollestad.date.DatePicker视图。随后对参数做前置校验check(minDate null || currentDate null || minDate.before(currentDate)) { Your minDate must be less than currentDate. } check(maxDate null || currentDate null || maxDate.after(currentDate)) { Your maxDate must be bigger than currentDate. }即若同时提供了currentDate与minDate则minDate必须早于currentDate若同时提供了currentDate与maxDate则maxDate必须晚于currentDate否则直接抛出IllegalStateException中断配置。在 UI 交互层面源码给 DatePicker 注册了日期变化监听一旦用户改动日期就会结合requireFutureDate动态控制“确定”按钮的可用状态调用setActionButtonEnabled(POSITIVE, ...)。当requireFutureDate true时还会额外注册一个 TimeChangeListener 来监听系统时间变化详见下文“未来时间约束的实现”小节。读取当前选中日期对话框显示期间可通过以下方法随时获取当前选中的日期CheckResult fun MaterialDialog.selectedDate(): Calendar实现上直接调用内部 DatePicker 的getDate()见 DatePickerExt.kt。时间选择器timePicker基础用法MaterialDialog(this).show { timePicker { dialog, time - // time 为选中的时间类型为 java.util.Calendar } }完整参数说明timePicker的完整签名见 TimePickerExt.ktfun MaterialDialog.timePicker( currentTime: Calendar? null, requireFutureTime: Boolean false, show24HoursView: Boolean true, timeCallback: DateTimeCallback null ): MaterialDialog参数类型默认值作用currentTimeCalendar?null初始化时显示的时间为null时默认显示当前时间requireFutureTimeBooleanfalse为true时强制所选时间必须晚于当前时刻show24HoursViewBooleantrue是否以 24 小时制显示false则显示 AM/PM 12 小时制timeCallbackDateTimeCallbacknull点击确定后的结果回调内部实现要点timePicker内部加载布局 md_datetime_picker_time.xml该布局就是一个原生TimePicker控件。源码通过setIs24HourView(show24HoursView)应用小时制若提供了currentTime则把其中的HOUR_OF_DAY与MINUTE写入控件with(getTimePicker()) { setIs24HourView(show24HoursView) if (currentTime ! null) { hour(currentTime.get(Calendar.HOUR_OF_DAY)) minute(currentTime.get(Calendar.MINUTE)) } ... }值得注意的兼容性细节在 ViewExt.kt 中读写hour/minute都做了 API 级别判断——Android 7.0NougatAPI 24及以上使用新的TimePicker.getHour()/setHour()以下则退回currentHour/currentMinute保证低版本兼容。回调同样发生在点击“确定”时此时源码调用getTimePicker().toCalendar()把 TimePicker 的时分组合进一个表示“今天”的Calendar实例返回见 DateTimeExt.kt。读取当前选中时间可使用CheckResult fun MaterialDialog.selectedTime(): Calendar日期时间选择器dateTimePicker基础用法dateTimePicker把日期与时间整合到同一个对话框中内部使用一个ViewPager在“日期页”与“时间页”之间滑动切换顶部带圆点指示器MaterialDialog(this).show { dateTimePicker(requireFutureDateTime true) { _, dateTime - // dateTime 为选中的日期时间类型为 java.util.Calendar } }完整参数说明dateTimePicker的完整签名见 DateTimePickerExt.ktfun MaterialDialog.dateTimePicker( minDateTime: Calendar? null, maxDateTime: Calendar? null, currentDateTime: Calendar? null, requireFutureDateTime: Boolean false, show24HoursView: Boolean false, autoFlipToTime: Boolean true, dateTimeCallback: DateTimeCallback null ): MaterialDialog参数类型默认值作用minDateTimeCalendar?null可选的最早日期时间maxDateTimeCalendar?null可选的最晚日期时间currentDateTimeCalendar?null初始化时选中的日期时间为null时日期默认今天、时间默认12:00requireFutureDateTimeBooleanfalse为true时强制所选日期时间必须晚于当前时刻show24HoursViewBooleanfalse是否 24 小时制注意与timePicker的默认值相反autoFlipToTimeBooleantrue选中日期后是否自动滑动翻页到时间选择页dateTimeCallbackDateTimeCallbacknull点击确定后的结果回调需要注意原文档中“maxDate”实为maxDateTime的笔误本文以源码签名为准。双页 ViewPager 的结构与翻页逻辑从布局 md_datetime_picker_pager.xml 可以看出dateTimePicker由上下两部分组成顶部是com.afollestad.viewpagerdots.DotsIndicator圆点指示器底部是自定义的WrapContentViewPager其中include了日期页与时间页两个布局。DateTimePickerAdapter 是一个仅含两个页面的PagerAdapterposition 0 →datetimeDatePicker日期页position 1 →datetimeTimePicker时间页。DateTimePickerExt.kt在初始化时给 ViewPager 设置该适配器并让DotsIndicator通过attachViewPager(viewPager)与 ViewPager 绑定圆点颜色取自主题的textColorPrimary。两个值得展开的实现细节自适应高度标准ViewPager在wrap_content下高度测量不稳定因此模块自定义了 WrapContentViewPager在onMeasure中遍历所有子页测量各自高度取最大值且不超过父容器允许高度作为 ViewPager 的精确高度保证日期页与时间页切换时不跳动。自动翻页autoFlipToTime当用户在日期页选完日期后addOnDateChanged监听里会判断日期是否确实发生变化通过比较dayOfMonth见didDateChange若变化且autoFlipToTime true则执行getPager().currentItem 1自动滑到时间页减少一次手动操作。若autoFlipToTime false用户可在两页之间自由滑动。默认时间当未提供currentDateTime时源码默认把时间初始化为12:00hour(... ?: 12)、minute(... ?: 0)而不是当前时刻这一点在业务上需要注意。点击“确定”后源码调用toCalendar(getDatePicker(), getTimePicker())将日期页的Calendar与时间页的时分合并得到完整的日期时间结果。对话框显示期间可用selectedDateTime()读取当前选中值CheckResult fun MaterialDialog.selectedDateTime(): Calendar“仅限未来”约束的实现原理三个 Picker 都支持requireFutureXxx这类“未来时间约束”其核心机制可以概括为实时校验 确定按钮联动。以dateTimePicker为例校验逻辑位于 DateTimeExt.ktinternal fun isFutureTime(datePicker: DatePicker, timePicker: TimePicker): Boolean { val now Calendar.getInstance() val dateTime toCalendar(datePicker, timePicker) return dateTime.timeInMillis now.timeInMillis }即把当前选中的日期时间与Calendar.getInstance()的当前时刻比较只要选中值的时间戳不小于当前时间戳即为“未来”。每当用户改变日期或时间addOnDateChanged/setOnTimeChangedListener源码就会重新计算该布尔值并调用setActionButtonEnabled(POSITIVE, ...)动态启用/禁用“确定”按钮从而阻止用户在约束不满足时提交。还有一个容易被忽略的边界场景对话框保持打开跨越了系统时间变化。为此模块实现了 TimeChangeListener——一个基于BroadcastReceiver的监听器注册了三个系统广播Intent.ACTION_TIME_TICK每分钟的系统时间变化广播Intent.ACTION_TIMEZONE_CHANGED时区变化Intent.ACTION_TIME_CHANGED用户手动改时间。一旦监测到小时或分钟发生变化就触发回调重新校验“未来”状态并刷新按钮可用性。该监听器在对话框onDismiss时会调用dispose()注销广播接收器避免内存泄漏。这也是requireFutureXxx true场景下源码额外实例化TimeChangeListener的原因。横竖屏适配与布局细节三个 Picker 在加载自定义布局时都使用了同一个技巧见三个扩展文件中的customView调用customView( R.layout.md_datetime_picker_xxx, noVerticalPadding true, dialogWrapContent windowContext.isLandscape() )含义是去掉对话框自定义视图的垂直内边距并在横屏时让对话框高度自适应内容wrapContent为横向屏幕保留更多可用空间。这是该模块在常见手机上横竖屏切换时的默认适配策略。此外日期页与时间页的布局都相当轻量日期页 md_datetime_picker_date.xml 仅包含一个com.afollestad.date.DatePicker自定义日历控件并设置了date_picker_calendar_horizontal_padding8dp时间页 md_datetime_picker_time.xml 仅包含一个原生TimePicker。布局中相关尺寸定义集中在 datetime/src/main/res/values/dimens.xml公共资源 ID 则在 datetime/src/main/res-public/values/public.xml 中声明。完整实战示例综合以上内容下面给出一个覆盖三个 Picker 的完整示例包含“未来时间约束 24 小时制 结果读取”的典型组合import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.datetime.datePicker import com.afollestad.materialdialogs.datetime.dateTimePicker import com.afollestad.materialdialogs.datetime.selectedDate import com.afollestad.materialdialogs.datetime.selectedDateTime import com.afollestad.materialdialogs.datetime.selectedTime import com.afollestad.materialdialogs.datetime.timePicker import java.util.Calendar // 日期选择限定在 2024-01-01 与 2025-12-31 之间初始选中今天 val minDate Calendar.getInstance().apply { set(2024, Calendar.JANUARY, 1) } val maxDate Calendar.getInstance().apply { set(2025, Calendar.DECEMBER, 31) } MaterialDialog(this).show { datePicker( minDate minDate, maxDate maxDate, currentDate Calendar.getInstance() ) { _, date - val y date.get(Calendar.YEAR) val m date.get(Calendar.MONTH) 1 val d date.get(Calendar.DAY_OF_MONTH) // 业务处理$y-$m-$d } } // 时间选择12 小时制AM/PM仅允许未来时间 MaterialDialog(this).show { timePicker( currentTime Calendar.getInstance(), requireFutureTime true, show24HoursView false ) { _, time - // time.get(Calendar.HOUR_OF_DAY)、time.get(Calendar.MINUTE) } } // 日期时间选择仅限未来24 小时制选完日期自动翻到时间页 MaterialDialog(this).show { dateTimePicker( requireFutureDateTime true, show24HoursView true, autoFlipToTime true ) { _, dateTime - // dateTime 是合并了日期页与时间页的完整 Calendar } }若需要在对话框尚未关闭时读取当前选中值例如与其他 UI 联动可使用selectedDate()、selectedTime()、selectedDateTime()三个CheckResult方法。与核心模块的关系及扩展思路datetime模块本身没有独立的MaterialDialog实现所有能力都建立在核心模块之上。三个扩展函数内部统一依赖核心模块的以下 API可在 core/src/main/java/com/afollestad/materialdialogs/ 下查看customView(...)把 Picker 布局注入对话框内容区来自 customview/DialogCustomViewExt.ktpositiveButton/negativeButton绑定“确定/取消”按钮来自 actions/DialogActionExt.ktsetActionButtonEnabled动态控制按钮可用性onDismiss注册关闭回调用于清理广播监听器来自 callbacks/DialogCallbackExt.kt。这也意味着你可以复用本文的扩展思路在MaterialDialog.show { }块内把日期时间选择与标题、消息、输入框、列表等核心模块特性自由组合构建更复杂的表单对话框。对核心模块的整体能力可进一步参考 documentation/CORE.md。小结datetime模块通过三个 Kotlin 扩展函数为MaterialDialog提供日期、时间、日期时间三种 Picker依赖引入只需coredatetime两个坐标。datePicker支持minDate/maxDate/currentDate/requireFutureDatetimePicker支持currentTime/requireFutureTime/show24HoursViewdateTimePicker额外支持minDateTime/maxDateTime/currentDateTime/autoFlipToTime等参数并基于 ViewPager 实现日期、时间双页滑动切换。所有“仅限未来”约束均由“实时校验 确定按钮禁用联动”实现并通过TimeChangeListener监听系统时间/时区变化以处理跨时刻的边界情况。回调统一返回java.util.Calendar配合selectedDate()/selectedTime()/selectedDateTime()可在对话框存活期间随时读取当前选中值。参考资料官方模块文档见 documentation/DATETIME.md对应实现源码见 datetime/src/main/java/com/afollestad/materialdialogs/datetime/。赞分享UI组件移动开发【免费下载链接】material-dialogs A beautiful, fluid, and extensible dialogs API for Kotlin Android.项目地址https://gitcode.com/gh_mirrors/ma/material-dialogs点击查看免费下载相关推荐Material-Dialogs 日期时间选择器使用指南Material Dialogs 日期时间选择器使用指南 概述 Material Dialogs 是一个遵循 Material Design 规范的对话框库其UI组件移动开发**日期时间选择利器 —— vue-datetime**日期时间选择利器 —— vue datetime 在快速发展的前端领域易用且高效的UI组件一直是开发者追求的重点。尽管 vue datetime 项目已不再维CodeLite数据库工具使用指南SQLite、MySQL、PostgreSQL的集成开发CodeLite数据库工具使用指南SQLite、MySQL、PostgreSQL的集成开发 CodeLite是一款功能强大的多用途IDE专注于C/C/R开发工具IDE代码编辑器桌面应用上一篇解决React Beautiful DND服务端渲染难题从窗口对象到尺寸计算的完整方案下一篇React Beautiful DND 性能基准测试拖拽 1000 项时的性能表现与优化方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考