10

Using MaterialDatePicker I want to show required date and give an opportunity to select another. But when a DatePicker appears it shows current date instead of specified.

I plug the library: implementation 'com.google.android.material:material:1.2.0-alpha06' (or 1.1.0).

Then override AppTheme in styles.xml:

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

And now can show 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) }

This is a result. I want to show 1st November, but it shows 7th May.

enter image description here

UPDATE 1

As written in above link, we can use 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)
...

This will show required date, we can select another day, but we cannot scroll months.

enter image description here

UPDATE 2

I suppose this is a bug of a new Android DatePicker. So I have to select well-known library https://github.com/wdullaer/MaterialDateTimePicker. It selects a specified date right and doesn't require changing an original theme.

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • 2
    You need to read how ConstrainBuilder works. The start/end are Milliseconds since Epoch _representing the instant of time_ that contains the "MONTH" you're interested in display as start or end. `setSelection` is the same, but indicating what value is selected, which doesn't mean which value will the picker open at. That's what `openAt` is for. You always have to remember that you need Miliseconds since Epoch. You cannot know how many MS elapsed since just a date, you need a ZonedDateTime. – Martin Marconcini May 07 '20 at 17:46
  • 1
    setStart/End effectively stop showing the months before and after. It's all it does. It saves you validation if you KNOW you want a date between certain "months". The Day Part is (as far as I remember), absolutely ignored (but it may have changed in later revisions). See Gabrielle's answer down below. That's the correct way of doing it with Java 8 (or ThreeTenABP if you don't have access to Gradle 4.x and/or API 26++, and therefore can't access Java 8 time.* api) – Martin Marconcini May 07 '20 at 17:48
  • 1
    What I mean is: you're blaming the wrong subject here. Material Date Picker is a piece of UX Garbage, but it works. The "Well Known Library" you have is ok, but it's absolutely not needed and it suffers from the exact same problems and discoverability nightmares because it's a "copy" of the Material Design implementation, plus a bunch of other inconsistencies in spacing, elevation, etc. So, it's the same crap :) – Martin Marconcini May 07 '20 at 17:50
  • 1
    @MartinMarconcini, my applause to you! :) Very interesting narration. You have a great experience! – CoolMind May 08 '20 at 08:08
  • 1
    Thanks. I'm glad it was of service. I would have written an answer, but the existing one is absolutely valid. I just wanted to make sure you understood what was going on and why "zoning" a local time is needed to obtain its "time" which is what calendar constrains uses... a very odd decision, but this is Android where if things cannot be polished, they will be released anyway and maybe polished 3 years later when the new "cool" patterns emerge. :) Have a nice date picking and make sure to let Google know when your users can't figure out how to change the year w/out scrolling ;) – Martin Marconcini May 08 '20 at 09:19
  • @MartinMarconcini, thank you very much for details! I see you like to give a good feedback. I seldom see so experienced programmers as you, was glad to hear about those libraries and Google. :))) Have a good day! – CoolMind May 08 '20 at 10:13
  • @MartinMarconcini, I have been struggling with Material theme for several days. Buttons, AlertDialogs, colors of DatePicker... I suspect, it is not the end. Do you use `Theme.MaterialComponents.Light.DarkActionBar` or similar in your projects? – CoolMind May 12 '20 at 16:27
  • Themeing on Android has gotten better, but its discoverability is still a major pain. I suggest you post your specific questions in the hopes people can help you with individual problems. I sometimes hang on this chat if you need specific assistance (although I'm not always there, and I don't always answer all the questions I get, but I try to donate some free time) https://chat.stackoverflow.com/rooms/210228/android-help – Martin Marconcini May 13 '20 at 08:59
  • @MartinMarconcini, thank you! I appreciate your help to the community. By the way, thanks for the tip about time zone in a date format. I hadn't used that for ages. – CoolMind May 13 '20 at 09:56

1 Answers1

10

You can set the month to which the picker opens with the method constraintsBuilder.setOpenAt(). The default value is the current month if within the bounds otherwise the earliest month within the bounds:

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());

You can set a default selection (defaults to no selection) with:

builder.setSelection(....);

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841