【问题标题】:Restrict Range in Android DatePicker Custom Dialog在 Android DatePicker 自定义对话框中限制范围
【发布时间】:2016-06-30 11:40:38
【问题描述】:

我有一个自定义线性布局,其中包含 DatePickerTimePicker 小部件。这用作DateTime 选择器。我想通过setMaxDate()setMinDate() 来限制DatePicker。我已经完成了:

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

当对话框出现时,超出此范围的日期实际上是灰色的。但我仍然可以选择一个灰色的日期。我偶然发现了this。但是,其中包含 datepicker 的自定义布局有什么解决方法?

【问题讨论】:

    标签: android datepicker material-components-android android-datepicker material-components


    【解决方案1】:

    给未来的读者!

    实际上,使用新的android material design components 可以使用MaterialDatePicker 实现您想要实现的目标。超出允许范围的日期是不可选择的。


    步骤

    1.将材料依赖添加到模块的 gradle 文件中

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

    2。更改应用主题以继承材料主题的版本。

    例如:

    <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)
            }
        }
    
    }
    

    【讨论】:

    【解决方案2】:

    材质组件库提供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());
    

    【讨论】:

    • 现在您所要做的就是迁移到 Material 主题并观看您的应用程序爆炸。即使是 Bridge 主题也无助于减轻崩溃。所有部件都应手动检查
    • @Farid 答案是关于具有 MaterialDatePicker 的验证器,而不是需要使用的主题。
    【解决方案3】:

    如果有人想要 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)
         }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2014-07-29
      相关资源
      最近更新 更多