Ограничить диапазон в пользовательском диалоговом окне Android DatePicker

У меня есть собственный линейный макет, в котором есть виджеты DatePicker и TimePicker. Это используется как средство выбора DateTime. Я хочу ограничить DatePicker с помощью setMaxDate() и setMinDate(). Я сделал:

dp.setMaxDate(new DateTime().minusDays(1).getMillis());
dp.setMinDate(new DateTime().minusDays(30).getMillis());

Даты за пределами этого диапазона фактически отображаются серым цветом при появлении диалогового окна. Но я все еще могу выбрать серую дату. Я наткнулся на это. Но как обойти пользовательский макет с помощью средства выбора даты?


person Vivekanand P V    schedule 15.03.2016    source источник


Ответы (3)


Для будущих читателей!

На самом деле с новыми компонентами материального дизайна Android то, чего вы хотите достичь, может быть достигнуто с помощью MaterialDatePicker. Даты за пределами допустимого диапазона выбрать нельзя.

ограниченный диапазон выбора даты


Шаги

<сильный>1. Добавьте материальную зависимость в файл gradle вашего модуля

implementation 'com.google.android.material:material:1.1.0-beta01'

<сильный>2. Измените тему приложения, чтобы она наследовалась от версии материальной темы.

ex:

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

<сильный>3. Используйте следующий код, чтобы открыть диалоговое окно.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        setupRangePickerDialog()

    }

    private fun setupRangePickerDialog() {
        val builderRange = MaterialDatePicker.Builder.dateRangePicker()

        builderRange.setCalendarConstraints(limitRange().build())
        val pickerRange = builderRange.build()
        pickerRange.show(supportFragmentManager, pickerRange.toString())
    }


    /*
    Limit selectable range to Oct 17 - Nov 20 2019
     */
    private fun limitRange(): CalendarConstraints.Builder {

        val constraintsBuilderRange = CalendarConstraints.Builder()

        val calendarStart: Calendar = GregorianCalendar.getInstance()
        val calendarEnd: Calendar = GregorianCalendar.getInstance()

        val year = 2019

        calendarStart.set(year, 10, 17)
        calendarEnd.set(year, 11, 20)

        val minDate = calendarStart.timeInMillis
        val maxDate = calendarEnd.timeInMillis

        constraintsBuilderRange.setStart(minDate)
        constraintsBuilderRange.setEnd(maxDate)

        constraintsBuilderRange.setValidator(RangeValidator(minDate, maxDate))

        return constraintsBuilderRange
    }


}

class RangeValidator(private val minDate:Long, private val maxDate:Long) : CalendarConstraints.DateValidator{


    constructor(parcel: Parcel) : this(
        parcel.readLong(),
        parcel.readLong()
    )

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        TODO("not implemented")
    }

    override fun describeContents(): Int {
        TODO("not implemented")
    }

    override fun isValid(date: Long): Boolean {
        return !(minDate > date || maxDate < date)

    }

    companion object CREATOR : Parcelable.Creator<RangeValidator> {
        override fun createFromParcel(parcel: Parcel): RangeValidator {
            return RangeValidator(parcel)
        }

        override fun newArray(size: Int): Array<RangeValidator?> {
            return arrayOfNulls(size)
        }
    }

}
person user158    schedule 12.10.2019
comment
Вы можете использовать темы Bridge, если не можете полностью изменить старую тему: github.com/material-components/material-components-android/blob/ - person Ely Dantas; 17.11.2020
comment
Как мы можем объявить это в файле макета XML? - person IgorGanapolsky; 03.01.2021

Библиотека компонентов материалов предоставляет MaterialDatePicker.
Вы можете использовать DateValidator для ограничения выбора.
В частности, вы можете использовать встроенные средства проверки:

  • DateValidatorPointForward, который включает даты с заданной точки вперед
  • DateValidatorPointBackward, который включает только даты до заданной точки.

Что-то вроде:

MaterialDatePicker.Builder<Pair<Long, Long>> builderRange = MaterialDatePicker.Builder.dateRangePicker();
CalendarConstraints.Builder constraintsBuilderRange = new CalendarConstraints.Builder();

//....define min and max for example with LocalDateTime and ZonedDateTime or Calendar

CalendarConstraints.DateValidator dateValidatorMin = DateValidatorPointForward.from(min.getTimeInMillis());
CalendarConstraints.DateValidator dateValidatorMax = DateValidatorPointBackward.before(max.getTimeInMillis());

ArrayList<CalendarConstraints.DateValidator> listValidators =
            new ArrayList<CalendarConstraints.DateValidator>();
listValidators.add(dateValidatorMin);
listValidators.add(dateValidatorMax);
CalendarConstraints.DateValidator validators = CompositeDateValidator.allOf(listValidators);
constraintsBuilderRange.setValidator(validators);

builderRange.setCalendarConstraints(constraintsBuilderRange.build());
MaterialDatePicker<Pair<Long, Long>> pickerRange = builderRange.build();
pickerRange.show(getSupportFragmentManager(), pickerRange.toString());

введите описание изображения здесь

person Gabriele Mariotti    schedule 29.05.2020
comment
Теперь все, что вам нужно сделать, это перейти на тему Material и посмотреть, как ваше приложение взорвется. Даже темы Bridge не помогут смягчить сбои. Все детали должны быть проверены вручную - person Farid; 05.03.2021
comment
@Farid, ответ касается валидатора с MaterialDatePicker, а не темы, которую необходимо использовать. - person Gabriele Mariotti; 05.03.2021

Если кому-то нужен RangeValidator (опубликовано выше), но с меньшим количеством кода: добавлена ​​аннотация (@Parcelize)

@Parcelize
internal class RangeValidator(
private var minDate: Long = 0,
private var maxDate: Long = 0) : DateValidator {

     override fun isValid(date: Long): Boolean {
         return !(minDate > date || maxDate < date)
     }
}
person Eugene Voronoy    schedule 07.12.2020
comment
Ты мужчина Евгений - person Daniel Wilson; 12.01.2021