Search code examples
androidmaterial-components-androidmaterial-components

How to validate Material RangeDatePicker from first selection(point) in Android?


I want validate range-date-picker from first selection to 6 month but I couldn't.

enter image description here Tried to catch(detect) first user selection(date) on range picker from this 'CalendarConstraints.Builder()'

        val constDate = CalendarConstraints.Builder()
        constDate.setValidator(object : CalendarConstraints.DateValidator {
              ...

             //this code not work correctly
              override fun isValid(date: Long): Boolean {
                   val calendar = Calendar.getInstance()
                if (initTime == 0.toLong())
                    initTime = System.currentTimeMillis()
                return if (System.currentTimeMillis() > initTime + 1000) {
                    Log.e("DateActivity", "isValid: 크다")
                    if (firstOrder == 0) {
                        firstSelect = date
                        firstOrder++
                        calendar.time = Date(firstSelect)
                        calendar.add(Calendar.MONTH, 6)
                    }
                    val remainDate = Calendar.getInstance()
                    remainDate.time = Date(date)
                    calendar > remainDate
                } else {
                    Log.e("DateActivity", "isValid: 크지 않다.")
                    true
                }
              }
        }

        builder.setCalendarConstraints(constDate.build())
        val picker = builder.build()

By time difference(System.currentTimeMillis()) try to catch first selection but when swipe picker other date catched in override fun isValid() . so I tried setOnTouchListener{} but no found way picker's setOnTouchListener in override fun isValid() cause picker built after CalendarConstraints set.

This is just static validation. I Think.

https://stackoverflow.com/a/58354878/13050313
https://stackoverflow.com/a/62080184/13050313


Solution

  • Now, I don't need this function what I asked 7 month ago, but I got this now.

    //global
    private const val RESET_TIME_MILLIS = 1500L
    private var TERM_CALENDAR: Calendar = Calendar.getInstance()
    private const val DAY_OF_TERM = 60
    
    //prperties of Fragment or Activity
    private val calendar = Calendar.getInstance()
    private var firstSelect: Calendar? = null
    private var secondSelect: Calendar? = null
    
    //setValidator(below object)
    object : CalendarConstraints.DateValidator {
    
        private val dayList = arrayListOf<Calendar>()
        private var job: Job? = null
    
        override fun isValid(date: Long): Boolean {
            if (job == null) {
                job = lifecycleScope.launch {
                    delay(RESET_TIME_MILLIS)
                    if (secondSelect != null) {
                        firstSelect = null
                        secondSelect = null
                    }
                    dayList.clear()
                }
            } else {
                if (job!!.isCompleted) {
                    job = null
                }
            }
            calendar.time = Date(date)
            val instancCal = Calendar.getInstance().apply {
                time = Date(date)
            }
            dayList.add(instancCal)
    
            if (calendar.dayOfMonth() == 1 && dayList.count() == 2) {
                if (firstSelect == null) {
                    firstSelect = dayList[0]
                    TERM_CALENDAR.apply {
                        set(Calendar.YEAR, firstSelect!!.get(Calendar.YEAR))
                        set(Calendar.MONTH, firstSelect!!.get(Calendar.MONTH))
                        set(Calendar.DAY_OF_MONTH, firstSelect!!.get(Calendar.DAY_OF_MONTH))
                        add(
                            Calendar.DAY_OF_MONTH,
                            DAY_OF_TERM
                        )
                    }
                } else if (secondSelect == null) {
                    secondSelect = dayList[0]
                }
            }
            if (secondSelect != null) {
                if (calendar in firstSelect!!..TERM_CALENDAR) {
                    return true
                }
                return false
            }
            return if (firstSelect == null) {
                true
            } else {
                calendar in firstSelect!!..TERM_CALENDAR
            }
        }
    
        override fun describeContents(): Int {
            return 0
        }
    
        override fun writeToParcel(dest: Parcel?, flags: Int) {
        }
    }
    

    It is like this (valid from selected to 60days)

    bandicam 2021-02-18 20-58-01-795