diff options
author | Alan Viverette <alanv@google.com> | 2014-10-24 14:34:26 -0700 |
---|---|---|
committer | Alan Viverette <alanv@google.com> | 2014-10-24 14:37:29 -0700 |
commit | 50eb025c2fea7e364e0be951ce8ba6ca605f901a (patch) | |
tree | 2c61860100aafc3adfef66a5912fa2204aa6e892 /core/java/android/widget | |
parent | cc66a236f90cbef7f9562b4179c3aec517f4f082 (diff) | |
download | frameworks_base-50eb025c2fea7e364e0be951ce8ba6ca605f901a.zip frameworks_base-50eb025c2fea7e364e0be951ce8ba6ca605f901a.tar.gz frameworks_base-50eb025c2fea7e364e0be951ce8ba6ca605f901a.tar.bz2 |
Fix min/max date range in DatePicker calendar mode
Also cleans abstraction of various day/year pickers and adapters.
BUG: 18104457
Change-Id: Ifde664788d8123a3123303940bac63c1350c2cd7
Diffstat (limited to 'core/java/android/widget')
-rw-r--r-- | core/java/android/widget/DatePickerCalendarDelegate.java | 40 | ||||
-rw-r--r-- | core/java/android/widget/DatePickerController.java | 15 | ||||
-rw-r--r-- | core/java/android/widget/DayPickerView.java | 69 | ||||
-rw-r--r-- | core/java/android/widget/SimpleMonthAdapter.java | 65 | ||||
-rw-r--r-- | core/java/android/widget/SimpleMonthView.java | 20 | ||||
-rw-r--r-- | core/java/android/widget/YearPickerView.java | 32 |
6 files changed, 126 insertions, 115 deletions
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index e71b383..64c81e0 100644 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -21,13 +21,11 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; -import android.util.SparseArray; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.View; @@ -186,6 +184,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i headerSelectedTextColor)); mDayPickerView = new DayPickerView(mContext, this); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView = new YearPickerView(mContext); mYearPickerView.init(this); @@ -411,7 +411,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i updateDisplay(false); } mMinDate.setTimeInMillis(minDate); - mDayPickerView.goTo(getSelectedDay(), false, true, true); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView.setRange(mMinDate, mMaxDate); } @Override @@ -432,7 +433,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i updateDisplay(false); } mMaxDate.setTimeInMillis(maxDate); - mDayPickerView.goTo(getSelectedDay(), false, true, true); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView.setRange(mMinDate, mMaxDate); } @Override @@ -454,36 +456,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } @Override - public int getMinYear() { - return mMinDate.get(Calendar.YEAR); - } - - @Override - public int getMaxYear() { - return mMaxDate.get(Calendar.YEAR); - } - - @Override - public int getMinMonth() { - return mMinDate.get(Calendar.MONTH); - } - - @Override - public int getMaxMonth() { - return mMaxDate.get(Calendar.MONTH); - } - - @Override - public int getMinDay() { - return mMinDate.get(Calendar.DAY_OF_MONTH); - } - - @Override - public int getMaxDay() { - return mMaxDate.get(Calendar.DAY_OF_MONTH); - } - - @Override public void setEnabled(boolean enabled) { mMonthAndDayLayout.setEnabled(enabled); mHeaderYearTextView.setEnabled(enabled); diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java index 059709d..ea6ec61 100644 --- a/core/java/android/widget/DatePickerController.java +++ b/core/java/android/widget/DatePickerController.java @@ -38,20 +38,5 @@ interface DatePickerController { void setFirstDayOfWeek(int firstDayOfWeek); int getFirstDayOfWeek(); - int getMinYear(); - int getMaxYear(); - - int getMinMonth(); - int getMaxMonth(); - - int getMinDay(); - int getMaxDay(); - - void setMinDate(long minDate); - Calendar getMinDate(); - - void setMaxDate(long maxDate); - Calendar getMaxDate(); - void tryVibrate(); } diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index ca4095e..fcf66f6 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -25,6 +25,7 @@ import android.os.Bundle; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; +import android.util.MathUtils; import android.view.View; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; @@ -57,9 +58,11 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, // highlighted time private Calendar mSelectedDay = Calendar.getInstance(); - private SimpleMonthAdapter mAdapter; - private Calendar mTempDay = Calendar.getInstance(); + private Calendar mMinDate = Calendar.getInstance(); + private Calendar mMaxDate = Calendar.getInstance(); + + private SimpleMonthAdapter mAdapter; // which month should be displayed/highlighted [0-11] private int mCurrentMonthDisplayed; @@ -75,6 +78,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, public DayPickerView(Context context, DatePickerController controller) { super(context); + init(); setController(controller); } @@ -97,6 +101,41 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, setUpListView(); } + public void setRange(Calendar minDate, Calendar maxDate) { + mMinDate.setTimeInMillis(minDate.getTimeInMillis()); + mMaxDate.setTimeInMillis(maxDate.getTimeInMillis()); + + mAdapter.setRange(mMinDate, mMaxDate); + + if (constrainCalendar(mSelectedDay, mMinDate, mMaxDate)) { + goTo(mSelectedDay, false, true, true); + } + } + + /** + * Constrains the supplied calendar to stay within the min and max + * calendars, returning <code>true</code> if the supplied calendar + * was modified. + * + * @param value The calendar to constrain + * @param min The minimum calendar + * @param max The maximum calendar + * @return True if <code>value</code> was modified + */ + private boolean constrainCalendar(Calendar value, Calendar min, Calendar max) { + if (value.compareTo(min) < 0) { + value.setTimeInMillis(min.getTimeInMillis()); + return true; + } + + if (value.compareTo(max) > 0) { + value.setTimeInMillis(max.getTimeInMillis()); + return true; + } + + return false; + } + public void onChange() { setUpAdapter(); setAdapter(mAdapter); @@ -137,23 +176,16 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, setFriction(ViewConfiguration.getScrollFriction() * mFriction); } - private int getDiffMonths(Calendar start, Calendar end){ + private int getDiffMonths(Calendar start, Calendar end) { final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR); final int diffMonths = end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears; return diffMonths; } private int getPositionFromDay(Calendar day) { - final int diffMonthMax = getDiffMonths(mController.getMinDate(), mController.getMaxDate()); - int diffMonth = getDiffMonths(mController.getMinDate(), day); - - if (diffMonth < 0 ) { - diffMonth = 0; - } else if (diffMonth > diffMonthMax) { - diffMonth = diffMonthMax; - } - - return diffMonth; + final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate); + final int diffMonth = getDiffMonths(mMinDate, day); + return MathUtils.constrain(diffMonth, 0, diffMonthMax); } /** @@ -171,8 +203,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, * visible * @return Whether or not the view animated to the new location */ - public boolean goTo(Calendar day, boolean animate, boolean setSelected, - boolean forceScroll) { + public boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) { // Set the selected day if (setSelected) { @@ -464,10 +495,10 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, } // Figure out what month is showing. - int firstVisiblePosition = getFirstVisiblePosition(); - int month = firstVisiblePosition % 12; - int year = firstVisiblePosition / 12 + mController.getMinYear(); - Calendar day = Calendar.getInstance(); + final int firstVisiblePosition = getFirstVisiblePosition(); + final int month = firstVisiblePosition % 12; + final int year = firstVisiblePosition / 12 + mMinDate.get(Calendar.YEAR); + final Calendar day = Calendar.getInstance(); day.set(year, month, 1); // Scroll either forward or backward one month. diff --git a/core/java/android/widget/SimpleMonthAdapter.java b/core/java/android/widget/SimpleMonthAdapter.java index 3bad235..5aa78c8 100644 --- a/core/java/android/widget/SimpleMonthAdapter.java +++ b/core/java/android/widget/SimpleMonthAdapter.java @@ -28,21 +28,30 @@ import java.util.HashMap; * An adapter for a list of {@link android.widget.SimpleMonthView} items. */ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener { - private static final String TAG = "SimpleMonthAdapter"; + private final Calendar mMinDate = Calendar.getInstance(); + private final Calendar mMaxDate = Calendar.getInstance(); private final Context mContext; private final DatePickerController mController; - private Calendar mSelectedDay; + private Calendar mSelectedDay; private ColorStateList mCalendarTextColors; public SimpleMonthAdapter(Context context, DatePickerController controller) { mContext = context; mController = controller; + init(); setSelectedDay(mController.getSelectedDay()); } + public void setRange(Calendar min, Calendar max) { + mMinDate.setTimeInMillis(min.getTimeInMillis()); + mMaxDate.setTimeInMillis(max.getTimeInMillis()); + + notifyDataSetInvalidated(); + } + /** * Updates the selected day and related parameters. * @@ -68,10 +77,9 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @Override public int getCount() { - final int diffYear = mController.getMaxYear() - mController.getMinYear(); - final int diffMonth = 1 + mController.getMaxMonth() - mController.getMinMonth() - + 12 * diffYear; - return diffMonth; + final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); + final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); + return diffMonth + 12 * diffYear + 1; } @Override @@ -92,36 +100,34 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @SuppressWarnings("unchecked") @Override public View getView(int position, View convertView, ViewGroup parent) { - SimpleMonthView v; - HashMap<String, Integer> drawingParams = null; + final SimpleMonthView v; if (convertView != null) { v = (SimpleMonthView) convertView; - // We store the drawing parameters in the view so it can be recycled - drawingParams = (HashMap<String, Integer>) v.getTag(); } else { v = new SimpleMonthView(mContext); + // Set up the new view - AbsListView.LayoutParams params = new AbsListView.LayoutParams( + final AbsListView.LayoutParams params = new AbsListView.LayoutParams( AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); v.setLayoutParams(params); v.setClickable(true); v.setOnDayClickListener(this); + if (mCalendarTextColors != null) { v.setTextColor(mCalendarTextColors); } } - if (drawingParams == null) { - drawingParams = new HashMap<String, Integer>(); - } else { - drawingParams.clear(); - } - final int currentMonth = position + mController.getMinMonth(); - final int month = currentMonth % 12; - final int year = currentMonth / 12 + mController.getMinYear(); - int selectedDay = -1; + final int minMonth = mMinDate.get(Calendar.MONTH); + final int minYear = mMinDate.get(Calendar.YEAR); + final int currentMonth = position + minMonth; + final int month = currentMonth % 12; + final int year = currentMonth / 12 + minYear; + final int selectedDay; if (isSelectedDayInMonth(year, month)) { selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH); + } else { + selectedDay = -1; } // Invokes requestLayout() to ensure that the recycled view is set with the appropriate @@ -129,15 +135,15 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli v.reuse(); final int enabledDayRangeStart; - if (mController.getMinMonth() == month && mController.getMinYear() == year) { - enabledDayRangeStart = mController.getMinDay(); + if (minMonth == month && minYear == year) { + enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeStart = 1; } final int enabledDayRangeEnd; - if (mController.getMaxMonth() == month && mController.getMaxYear() == year) { - enabledDayRangeEnd = mController.getMaxDay(); + if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) { + enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeEnd = 31; } @@ -155,20 +161,25 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @Override public void onDayClick(SimpleMonthView view, Calendar day) { - if (day != null) { - onDayTapped(day); + if (day != null && isCalendarInRange(day)) { + onDaySelected(day); } } + private boolean isCalendarInRange(Calendar value) { + return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; + } + /** * Maintains the same hour/min/sec but moves the day to the tapped day. * * @param day The day that was tapped */ - protected void onDayTapped(Calendar day) { + private void onDaySelected(Calendar day) { mController.tryVibrate(); mController.onDayOfMonthSelected(day.get(Calendar.YEAR), day.get(Calendar.MONTH), day.get(Calendar.DAY_OF_MONTH)); + setSelectedDay(day); } } diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 59baaba..d2a37ac 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -52,8 +52,6 @@ import java.util.Locale; * within the specified month. */ class SimpleMonthView extends View { - private static final String TAG = "SimpleMonthView"; - private static final int DEFAULT_HEIGHT = 32; private static final int MIN_HEIGHT = 10; @@ -67,15 +65,15 @@ class SimpleMonthView extends View { private static final int DAY_SEPARATOR_WIDTH = 1; + private final Formatter mFormatter; + private final StringBuilder mStringBuilder; + private final int mMiniDayNumberTextSize; private final int mMonthLabelTextSize; private final int mMonthDayLabelTextSize; private final int mMonthHeaderSize; private final int mDaySelectedCircleSize; - // used for scaling to the device density - private static float mScale = 0; - /** Single-letter (when available) formatter for the day of week label. */ private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault()); @@ -92,9 +90,6 @@ class SimpleMonthView extends View { private Paint mMonthTitlePaint; private Paint mMonthDayLabelPaint; - private final Formatter mFormatter; - private final StringBuilder mStringBuilder; - private int mMonth; private int mYear; @@ -155,11 +150,14 @@ class SimpleMonthView extends View { this(context, attrs, R.attr.datePickerStyle); } - public SimpleMonthView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs); + public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } - final Resources res = context.getResources(); + public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + final Resources res = context.getResources(); mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface); mMonthTitleTypeface = res.getString(R.string.sans_serif); diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java index 2bf07f9..24ed7ce 100644 --- a/core/java/android/widget/YearPickerView.java +++ b/core/java/android/widget/YearPickerView.java @@ -18,7 +18,6 @@ package android.widget; import android.content.Context; import android.content.res.Resources; -import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; @@ -33,10 +32,15 @@ import com.android.internal.R; */ class YearPickerView extends ListView implements AdapterView.OnItemClickListener, OnDateChangedListener { + private final Calendar mMinDate = Calendar.getInstance(); + private final Calendar mMaxDate = Calendar.getInstance(); + + private final YearAdapter mAdapter; + private final int mViewSize; + private final int mChildSize; + private DatePickerController mController; - private YearAdapter mAdapter; - private int mViewSize; - private int mChildSize; + private int mSelectedPosition = -1; private int mYearSelectedCircleColor; @@ -72,15 +76,23 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener setOnItemClickListener(this); setDividerHeight(0); + + mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view); + setAdapter(mAdapter); + } + + public void setRange(Calendar min, Calendar max) { + mMinDate.setTimeInMillis(min.getTimeInMillis()); + mMaxDate.setTimeInMillis(max.getTimeInMillis()); + + updateAdapterData(); } public void init(DatePickerController controller) { mController = controller; mController.registerOnDateChangedListener(this); - mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view); updateAdapterData(); - setAdapter(mAdapter); onDateChanged(); } @@ -98,8 +110,9 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener private void updateAdapterData() { mAdapter.clear(); - final int maxYear = mController.getMaxYear(); - for (int year = mController.getMinYear(); year <= maxYear; year++) { + + final int maxYear = mMaxDate.get(Calendar.YEAR); + for (int year = mMinDate.get(Calendar.YEAR); year <= maxYear; year++) { mAdapter.add(year); } } @@ -173,12 +186,13 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener updateAdapterData(); mAdapter.notifyDataSetChanged(); postSetSelectionCentered( - mController.getSelectedDay().get(Calendar.YEAR) - mController.getMinYear()); + mController.getSelectedDay().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR)); } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { event.setFromIndex(0); event.setToIndex(0); |