Reputation: 1540
I'm using google material DatePicker and I want to set min and max date for the picker it self! This is my code
private fun getDatPikr(tv: MaterialTextView, title: String, pastDays: Boolean = false) {
val datePicker = MaterialDatePicker.Builder.datePicker()
.setTitleText(title)
.build()
datePicker.show(childFragmentManager, "MATERIAL_DATE_PICKER")
datePicker.addOnPositiveButtonClickListener {
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
calendar.time = Date(it)
val date = "${calendar.get(Calendar.DAY_OF_MONTH)}/ " +
"${calendar.get(Calendar.MONTH) + 1}/${calendar.get(Calendar.YEAR)}"
tv.text = date
}
}
Upvotes: 5
Views: 10722
Reputation: 304
I got a requirement to show calendar only 50 years back from the current date and 50 years ahead from current date. I achieved this using MaterialDatePicker.
For instance: if current date is 27/07/2022
Then my Min Date would be: 27/07/1972
And Max Date would be: 27/07/2072
Here's the code:
private var mSelectedDate: Long = MaterialDatePicker.todayInUtcMilliseconds()
binding.btnPickDate.setOnClickListener {
val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
val today = MaterialDatePicker.todayInUtcMilliseconds()
cal.timeInMillis = today
cal.set(cal[Calendar.YEAR] - 50, cal[Calendar.MONTH], cal[Calendar.DATE])
val fiftyYearsBack = cal.timeInMillis
cal.timeInMillis = today
cal.set(cal[Calendar.YEAR] + 50, cal[Calendar.MONTH], cal[Calendar.DATE])
val fiftyYearsAhead = cal.timeInMillis
val datePicker =
MaterialDatePicker.Builder.datePicker()
.setTitleText("Select date")
.setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
.setSelection(mSelectedDate)
.setTheme(R.style.Widget_AppTheme_MaterialDatePicker)
.setCalendarConstraints(
CalendarConstraints.Builder()
.setStart(fiftyYearsBack)
.setEnd(fiftyYearsAhead)
.setValidator(
DateValidatorFiftyYearRange(
fiftyYearsBack,
fiftyYearsAhead
)
)
.build()
).build()
datePicker.show(supportFragmentManager, "DP")
datePicker.addOnPositiveButtonClickListener {
val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.US)
mSelectedDate = it
}
}
And for the DateValidatorFiftyYearRange class
import android.os.Parcel
import android.os.Parcelable
import com.google.android.material.datepicker.CalendarConstraints.DateValidator
/**
* A {@link DateValidator} that allows only 50 years back and forth from the current date.
*/
class DateValidatorFiftyYearRange(private val start: Long, private val end: Long) : DateValidator {
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(p0: Parcel?, p1: Int) {
p0?.writeLong(start)
p0?.writeLong(end)
}
override fun isValid(date: Long): Boolean {
return date in start..end
}
override fun equals(other: Any?): Boolean {
return if (this === other) {
true
} else other is DateValidatorFiftyYearRange
}
override fun hashCode(): Int {
val hashedFields = arrayOf<Any>(start, end)
return hashedFields.contentHashCode()
}
companion object CREATOR : Parcelable.Creator<DateValidatorFiftyYearRange> {
override fun createFromParcel(parcel: Parcel): DateValidatorFiftyYearRange {
return DateValidatorFiftyYearRange(parcel)
}
override fun newArray(size: Int): Array<DateValidatorFiftyYearRange?> {
return arrayOfNulls(size)
}
}
constructor(parcel: Parcel) : this(parcel.readLong(), parcel.readLong())
}
And here's the style, just in case if you want to hide edit pen button on calendar:
<style name="Widget.AppTheme.MaterialDatePicker" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="materialCalendarHeaderToggleButton">@style/Widget.AppTheme.MaterialCalendar.HeaderToggleButton</item>
</style>
<style name="Widget.AppTheme.MaterialCalendar.HeaderToggleButton" parent="Widget.MaterialComponents.MaterialCalendar.HeaderToggleButton">
<item name="android:visibility">gone</item>
</style>
Upvotes: 1
Reputation: 870
As per new Material Date pickers we can set the end date by passing setValidater() in Calendar Constraints.
val constraintsBuilder=CalendarConstraints.Builder()
.setValidator(DateValidatorPointBackward.now())
So that the user can only select the backwards dates from today or any date.
Upvotes: 16
Reputation: 211
Try this
val constraint = CalendarConstraints.Builder()
.setValidator(DateValidatorPointBackward.before(Calendar.getInstance().timeInMillis - YEAR_18_IN_MILLI))
val datePicker = MaterialDatePicker.Builder.datePicker()
.setCalendarConstraints(constraint.build())
.setSelection(YEAR_18_IN_MILLI)
.setTitleText(getString(R.string.date_of_birth))
.build()
Upvotes: 2
Reputation: 21053
You can use CalendarConstraints
to set configuration . Something like below.
val calendar = Calendar.getInstance()
val upTo = calendar.timeInMillis
calendar.set(2020, 1, 15)
val startFrom = calendar.timeInMillis
val constraints =CalendarConstraints.Builder()
.setStart(startFrom)
.setEnd(upTo)
.build()
val datePicker = MaterialDatePicker.Builder.datePicker()
.setCalendarConstraints(constraints)
.setTitleText("title")
.build()
You can Also add a validator to constraints by implementing CalendarConstraints.DateValidator
. This will prevent the invalid date selection . Give it a try its showing some weird behavior on my device .
Found Similar thread. have a look at This thread.
Upvotes: 3
Reputation: 5
Please check the doc Min and Max
You can also do it from the code using this method:
datePicker.setMinDate("Set the min date in millis")
datePicker.setMaxDate("Set the max date in millis")
Check this answer: here
Upvotes: -2