在 Android DatePicker 自定义对话框中限制范围
Posted
技术标签:
【中文标题】在 Android DatePicker 自定义对话框中限制范围【英文标题】:Restrict Range in Android DatePicker Custom Dialog 【发布时间】:2016-06-30 11:40:38 【问题描述】:我有一个自定义线性布局,其中包含 DatePicker
和 TimePicker
小部件。这用作DateTime
选择器。我想通过setMaxDate()
和setMinDate()
来限制DatePicker。我已经完成了:
dp.setMaxDate(new DateTime().minusDays(1).getMillis());
dp.setMinDate(new DateTime().minusDays(30).getMillis());
当对话框出现时,超出此范围的日期实际上是灰色的。但我仍然可以选择一个灰色的日期。我偶然发现了this。但是,其中包含 datepicker 的自定义布局有什么解决方法?
【问题讨论】:
【参考方案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)
【讨论】:
如果您无法更改整个旧主题,您可以使用 Bridge 主题:github.com/material-components/material-components-android/blob/… 我们如何在 XML 布局文件中声明这个?【参考方案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)
【讨论】:
以上是关于在 Android DatePicker 自定义对话框中限制范围的主要内容,如果未能解决你的问题,请参考以下文章
我需要在android.widget.datepicker中自定义月份名称