From 7c597aee285f2fe4a13a24334493c6eadddd7939 Mon Sep 17 00:00:00 2001 From: Sam Blitzstein Date: Tue, 20 May 2014 20:50:05 -0700 Subject: Add API for setMinDate and setMaxDate By default, all dates are valid. For dates outside of a specified range, the numbers will be grayed out, and they may not be clicked. Bug: 15086596 Change-Id: I1aef6e305637e5045e929bc03cb5d78e4aed746c --- .../datetimepicker/date/DatePickerController.java | 6 ++ .../datetimepicker/date/DatePickerDialog.java | 44 ++++++++++++ .../android/datetimepicker/date/MonthAdapter.java | 2 +- src/com/android/datetimepicker/date/MonthView.java | 83 ++++++++++++++++++++++ .../datetimepicker/date/SimpleMonthAdapter.java | 2 +- .../datetimepicker/date/SimpleMonthView.java | 11 ++- 6 files changed, 143 insertions(+), 5 deletions(-) (limited to 'src/com/android') diff --git a/src/com/android/datetimepicker/date/DatePickerController.java b/src/com/android/datetimepicker/date/DatePickerController.java index f89580e..42989dd 100644 --- a/src/com/android/datetimepicker/date/DatePickerController.java +++ b/src/com/android/datetimepicker/date/DatePickerController.java @@ -19,6 +19,8 @@ package com.android.datetimepicker.date; import com.android.datetimepicker.date.DatePickerDialog.OnDateChangedListener; import com.android.datetimepicker.date.MonthAdapter.CalendarDay; +import java.util.Calendar; + /** * Controller class to communicate among the various components of the date picker dialog. */ @@ -40,5 +42,9 @@ public interface DatePickerController { int getMaxYear(); + Calendar getMinDate(); + + Calendar getMaxDate(); + void tryVibrate(); } diff --git a/src/com/android/datetimepicker/date/DatePickerDialog.java b/src/com/android/datetimepicker/date/DatePickerDialog.java index 14c6b6d..994fdf2 100644 --- a/src/com/android/datetimepicker/date/DatePickerDialog.java +++ b/src/com/android/datetimepicker/date/DatePickerDialog.java @@ -97,6 +97,8 @@ public class DatePickerDialog extends DialogFragment implements private int mWeekStart = mCalendar.getFirstDayOfWeek(); private int mMinYear = DEFAULT_START_YEAR; private int mMaxYear = DEFAULT_END_YEAR; + private Calendar mMinDate; + private Calendar mMaxDate; private HapticFeedbackController mHapticFeedbackController; @@ -376,6 +378,48 @@ public class DatePickerDialog extends DialogFragment implements } } + /** + * Sets the minimal date supported by this DatePicker. Dates before (but not including) the + * specified date will be disallowed from being selected. + * @param calendar a Calendar object set to the year, month, day desired as the mindate. + */ + public void setMinDate(Calendar calendar) { + mMinDate = calendar; + + if (mDayPickerView != null) { + mDayPickerView.onChange(); + } + } + + /** + * @return The minimal date supported by this DatePicker. Null if it has not been set. + */ + @Override + public Calendar getMinDate() { + return mMinDate; + } + + /** + * Sets the minimal date supported by this DatePicker. Dates after (but not including) the + * specified date will be disallowed from being selected. + * @param calendar a Calendar object set to the year, month, day desired as the maxdate. + */ + public void setMaxDate(Calendar calendar) { + mMaxDate = calendar; + + if (mDayPickerView != null) { + mDayPickerView.onChange(); + } + } + + /** + * @return The maximal date supported by this DatePicker. Null if it has not been set. + */ + @Override + public Calendar getMaxDate() { + return mMaxDate; + } + public void setOnDateSetListener(OnDateSetListener listener) { mCallBack = listener; } diff --git a/src/com/android/datetimepicker/date/MonthAdapter.java b/src/com/android/datetimepicker/date/MonthAdapter.java index e48b205..3ed88b0 100644 --- a/src/com/android/datetimepicker/date/MonthAdapter.java +++ b/src/com/android/datetimepicker/date/MonthAdapter.java @@ -37,7 +37,7 @@ public abstract class MonthAdapter extends BaseAdapter implements OnDayClickList private static final String TAG = "SimpleMonthAdapter"; private final Context mContext; - private final DatePickerController mController; + protected final DatePickerController mController; private CalendarDay mSelectedDay; diff --git a/src/com/android/datetimepicker/date/MonthView.java b/src/com/android/datetimepicker/date/MonthView.java index ca7fd89..1924890 100644 --- a/src/com/android/datetimepicker/date/MonthView.java +++ b/src/com/android/datetimepicker/date/MonthView.java @@ -120,6 +120,8 @@ public abstract class MonthView extends View { // used for scaling to the device density protected static float mScale = 0; + protected final DatePickerController mController; + // affects the padding on the sides of this view protected int mPadding = 0; @@ -179,12 +181,19 @@ public abstract class MonthView extends View { protected int mDayTextColor; protected int mTodayNumberColor; + protected int mDisabledDayTextColor; protected int mMonthTitleColor; protected int mMonthTitleBGColor; public MonthView(Context context) { + this(context, null); + } + + public MonthView(Context context, DatePickerController controller) { super(context); + mController = controller; + Resources res = context.getResources(); mDayLabelCalendar = Calendar.getInstance(); @@ -195,6 +204,7 @@ public abstract class MonthView extends View { mDayTextColor = res.getColor(R.color.date_picker_text_normal); mTodayNumberColor = res.getColor(R.color.blue); + mDisabledDayTextColor = res.getColor(R.color.date_picker_text_disabled); mMonthTitleColor = res.getColor(R.color.white); mMonthTitleBGColor = res.getColor(R.color.circle_background); @@ -530,10 +540,18 @@ public abstract class MonthView extends View { /** * Called when the user clicks on a day. Handles callbacks to the * {@link OnDayClickListener} if one is set. + *

+ * If the day is out of the range set by minDate and/or maxDate, this is a no-op. * * @param day The day that was clicked */ private void onDayClick(int day) { + // If the min / max date are set, only process the click if it's a valid selection. + if (isOutOfRange(mYear, mMonth, day)) { + return; + } + + if (mOnDayClickListener != null) { mOnDayClickListener.onDayClick(this, new CalendarDay(mYear, mMonth, day)); } @@ -542,6 +560,71 @@ public abstract class MonthView extends View { mTouchHelper.sendEventForVirtualView(day, AccessibilityEvent.TYPE_VIEW_CLICKED); } + /** + * @return true if the specified year/month/day are within the range set by minDate and maxDate. + * If one or either have not been set, they are considered as Integer.MIN_VALUE and + * Integer.MAX_VALUE. + */ + protected boolean isOutOfRange(int year, int month, int day) { + if (isBeforeMin(year, month, day)) { + return true; + } else if (isAfterMax(year, month, day)) { + return true; + } + + return false; + } + + private boolean isBeforeMin(int year, int month, int day) { + Calendar minDate = mController.getMinDate(); + if (minDate == null) { + return false; + } + + if (year < minDate.get(Calendar.YEAR)) { + return true; + } else if (year > minDate.get(Calendar.YEAR)) { + return false; + } + + if (month < minDate.get(Calendar.MONTH)) { + return true; + } else if (month > minDate.get(Calendar.MONTH)) { + return false; + } + + if (day < minDate.get(Calendar.DAY_OF_MONTH)) { + return true; + } else { + return false; + } + } + + private boolean isAfterMax(int year, int month, int day) { + Calendar maxDate = mController.getMaxDate(); + if (maxDate == null) { + return false; + } + + if (year > maxDate.get(Calendar.YEAR)) { + return true; + } else if (year < maxDate.get(Calendar.YEAR)) { + return false; + } + + if (month > maxDate.get(Calendar.MONTH)) { + return true; + } else if (month < maxDate.get(Calendar.MONTH)) { + return false; + } + + if (day > maxDate.get(Calendar.DAY_OF_MONTH)) { + return true; + } else { + return false; + } + } + /** * @return The date that has accessibility focus, or {@code null} if no date * has focus diff --git a/src/com/android/datetimepicker/date/SimpleMonthAdapter.java b/src/com/android/datetimepicker/date/SimpleMonthAdapter.java index b49b135..1c1b7cc 100644 --- a/src/com/android/datetimepicker/date/SimpleMonthAdapter.java +++ b/src/com/android/datetimepicker/date/SimpleMonthAdapter.java @@ -29,6 +29,6 @@ public class SimpleMonthAdapter extends MonthAdapter { @Override public MonthView createMonthView(Context context) { - return new SimpleMonthView(context); + return new SimpleMonthView(context, mController); } } diff --git a/src/com/android/datetimepicker/date/SimpleMonthView.java b/src/com/android/datetimepicker/date/SimpleMonthView.java index 6939fa8..9271590 100644 --- a/src/com/android/datetimepicker/date/SimpleMonthView.java +++ b/src/com/android/datetimepicker/date/SimpleMonthView.java @@ -19,10 +19,12 @@ package com.android.datetimepicker.date; import android.content.Context; import android.graphics.Canvas; +import java.util.Calendar; + public class SimpleMonthView extends MonthView { - public SimpleMonthView(Context context) { - super(context); + public SimpleMonthView(Context context, DatePickerController controller) { + super(context, controller); } @Override @@ -33,7 +35,10 @@ public class SimpleMonthView extends MonthView { mSelectedCirclePaint); } - if (mHasToday && mToday == day) { + // If we have a mindate or maxdate, gray out the day number if it's outside the range. + if (isOutOfRange(year, month, day)) { + mMonthNumPaint.setColor(mDisabledDayTextColor); + } else if (mHasToday && mToday == day) { mMonthNumPaint.setColor(mTodayNumberColor); } else { mMonthNumPaint.setColor(mDayTextColor); -- cgit v1.2.3