MaterialDatePicker - how to select max 3 months?

43 Views Asked by At

Android. Material Date Picker. How to make it possible for user to select up to only 3 months. Not 'today-and-max-3-months-in-the-past' but 'any date interval even years in past but up 3 months'

1

There are 1 best solutions below

0
Tauri On

set calendar constraints of 180 days for materialDatePicker pointed me in right direction but it is

  1. in Java
  2. enforces specific number in days (and not specific number of months)

so correct answer to my question in Kotlin would be:

import androidx.core.util.Pair
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.MaterialDatePicker
import java.util.concurrent.TimeUnit
import kotlinx.parcelize.Parcelize


@Parcelize
class RangeDateValidator(private val numberOfMonths: Int) : CalendarConstraints.DateValidator {

    private var rangePicker: MaterialDatePicker<*>? = null

    fun setDatePicker(rangePicker: MaterialDatePicker<*>?) {
        this.rangePicker = rangePicker
    }

    override fun isValid(date: Long): Boolean {

        val selection = rangePicker?.selection as? Pair<Long, Long>?
        if (selection != null) {
            val startIndex = selection.first.monthsSinceEpoch()
            val dateIndex = date.monthsSinceEpoch()

            if (dateIndex > startIndex + numberOfMonths - 1)
                return false

        }
        return true
    }
}

fun Long.monthsSinceEpoch(): Long {
    val date=Date(this)
    val instance = Calendar.getInstance()
        .apply { time = date }

    return instance.get(Calendar.YEAR)*MONTHS_IN_YEAR+instance.get(Calendar.MONTH)
}

private const val MONTHS_IN_YEAR = 12L

and (later)

 val rangeValidator = RangeDateValidator(3)
 val constraintsBuilder = CalendarConstraints.Builder() 
               .setValidator(CompositeDateValidator.allOf(
               listOf(rangeValidator,  
               DateValidatorPointBackward.now())))
 val dateRangePickerBuilder =
                MaterialDatePicker.Builder.dateRangePicker()
                 .setCalendarConstraints(constraintsBuilder.build())
 val dateRangePicker = dateRangePickerBuilder.build()
 validator.setDatePicker(dateRangePicker)
    
 activity?.supportFragmentManager?.let {
                dateRangePicker.show(it, CALENDAR_TAG)
            }

This solution have minor disadvantage: highligting could become incorrect.