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>
Also, please help me to improve my code.
Thank you.