MaterialDatePicker 显示当前日期而不是需要

Posted

技术标签:

【中文标题】MaterialDatePicker 显示当前日期而不是需要【英文标题】:MaterialDatePicker shows current date instead of needed 【发布时间】:2020-08-22 23:52:23 【问题描述】:

使用MaterialDatePicker 我想显示所需的日期并有机会选择另一个。但是当出现 DatePicker 时,它会显示当前日期而不是指定日期。

我插入库:implementation 'com.google.android.material:material:1.2.0-alpha06'(或 1.1.0)。

然后在styles.xml 中覆盖AppTheme

<style name="AppTheme" parent="Theme.MaterialComponents.Light">

现在可以显示 DatePicker。

val now = Calendar.getInstance()
now[Calendar.YEAR] = 2020
now[Calendar.MONTH] = 10
now[Calendar.DAY_OF_MONTH] = 1
val builder = MaterialDatePicker.Builder.datePicker()
builder.setSelection(now.timeInMillis)

val picker = builder.build()
fragmentManager?.let  picker.show(it, MaterialDatePicker::class.java.simpleName) 

这是一个结果。我想显示 11 月 1 日,但显示的是 5 月 7 日。

更新 1

如上链接所述,我们可以使用CalendarConstraints.Builder:

...
val constraintsBuilder = CalendarConstraints.Builder()
constraintsBuilder.setStart(now.timeInMillis)
constraintsBuilder.setEnd(now.timeInMillis)

val builder = MaterialDatePicker.Builder.datePicker()
builder.setCalendarConstraints(constraintsBuilder.build())
builder.setSelection(now.timeInMillis)
...

这将显示所需的日期,我们可以选择另一天,但我们不能滚动月份。

更新 2

我想这是一个新的 Android DatePicker 的错误。所以我必须选择知名库https://github.com/wdullaer/MaterialDateTimePicker。它选择正确的指定日期,并且不需要更改原始主题。

【问题讨论】:

您需要阅读 ConstrainBuilder 的工作原理。开始/结束是自 Epoch 表示时间瞬间以来的毫秒数,其中包含您感兴趣的“MONTH”显示为开始或结束。 setSelection 是一样的,只是表示选择了哪个值,并不代表选择器会打开哪个值。这就是openAt 的用途。您始终必须记住,自 Epoch 以来您需要毫秒。您无法知道自一个日期以来经过了多少 MS,您需要一个 ZonedDateTime。 setStart/End 有效地停止显示之前和之后的月份。这就是它所做的一切。如果您知道想要某个“月份”之间的日期,它可以节省您的验证。日部分(据我所知)完全被忽略(但在以后的修订版中可能已经改变)。请参阅下面加布里埃尔的回答。这是使用 Java 8(或 ThreeTenABP,如果您无权访问 Gradle 4.x 和/或 API 26++,因此无法访问 Java 8 时间。* api)的正确方法 我的意思是:你在这里责备错误的主题。 Material Date Picker 是一个 UX 垃圾,但它可以工作。您拥有的“知名库”还可以,但绝对不需要它,并且它会遇到完全相同的问题和可发现性噩梦,因为它是 Material Design 实现的“副本”,以及许多其他间距、高度、等等。所以,这是一样的废话:) @MartinMarconcini,我为你鼓掌! :) 非常有趣的叙述。您的体验很棒! 谢谢。我很高兴它有服务。我会写一个答案,但现有的答案是绝对有效的。我只是想确保您了解正在发生的事情以及为什么需要“分区”当地时间来获得其“时间”,这是日历约束使用的......一个非常奇怪的决定,但这是 Android,如果事情不能被打磨,它们无论如何都会被发布,并且可能会在 3 年后出现新的“酷”模式时被打磨。 :) 选择一个不错的日期,并确保在您的用户无法弄清楚如何在不滚动的情况下更改年份时让 Google 知道;) 【参考方案1】:

您可以使用 constraintsBuilder.setOpenAt() 方法设置选择器打开的月份。 如果在边界内,则默认值为当前月份,否则为边界内最早的月份:

CalendarConstraints.Builder constraintsBuilder = new CalendarConstraints.Builder();

LocalDateTime local = LocalDateTime.of(2020, 11, 1, 0, 0);
long openAt= local.atZone(ZoneId.ofOffset("UTC", ZoneOffset.UTC)).toInstant().toEpochMilli();
//you can also use Calendar.getInstance()...
constraintsBuilder.setOpenAt(openAt);

builder.setCalendarConstraints(constraintsBuilder.build());

您可以通过以下方式设置默认选择(默认为无选择):

builder.setSelection(....);

【讨论】:

今天不工作。这很奇怪 @Vlad,这很奇怪。我启动了一个应用程序,它显示了所需的日期(甚至是 2000 年),请参阅pastebin.com/CiVJgJUP。

以上是关于MaterialDatePicker 显示当前日期而不是需要的主要内容,如果未能解决你的问题,请参考以下文章

MaterialDatePicker 获取选定的日期

MaterialDatePicker,选择结束日期后应用程序崩溃

MaterialDatePicker 选择后返回不正确的日期

如何在 MaterialDatePicker 中禁用过去的日期?

如何在MaterialDatePicker中打开之前选择的日期?

角度材料日期选择器 - 仅选择日期