From 28104e1de5595a22a6987181b13ddeb192739afd Mon Sep 17 00:00:00 2001
From: Svetoslav Ganov
+ * Note: If the range is set to a value that does not include the currently + * selected date the value of this picker will be updated to the closest + * date in the range. + *
+ * + * @param startYear The start year of the range. + * @param endYear The end year of the range. + */ + public void setRange(int startYear, int endYear) { + // set ranges of the widgets + mYearPicker.setRange(startYear, endYear); + mTempCalendar.clear(); + Calendar startRangeDate = (Calendar) mTempCalendar.clone(); + startRangeDate.set(startYear, 0, 1); + Calendar endRangeDate = (Calendar) mTempCalendar.clone(); + endRangeDate.set(endYear, 11, 31); + mMiniMonthDayPicker.setRange(startRangeDate, endRangeDate); + + // update state if current date is outside of the range + mTempCalendar.set(Calendar.YEAR, getYear()); + mTempCalendar.set(Calendar.MONTH, getMonth()); + mTempCalendar.set(Calendar.DAY_OF_MONTH, getDayOfMonth()); + if (mTempCalendar.before(startRangeDate)) { + updateDate(startRangeDate.get(Calendar.YEAR), startRangeDate.get(Calendar.MONTH), + startRangeDate.get(Calendar.DAY_OF_MONTH)); + } else if (mTempCalendar.after(endRangeDate)) { + updateDate(endRangeDate.get(Calendar.YEAR), endRangeDate.get(Calendar.MONTH), + endRangeDate.get(Calendar.DAY_OF_MONTH)); + } + } + @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); diff --git a/core/java/android/widget/DayPicker.java b/core/java/android/widget/DayPicker.java index cdf51f7fb738..02805be9c3cd 100644 --- a/core/java/android/widget/DayPicker.java +++ b/core/java/android/widget/DayPicker.java @@ -366,22 +366,38 @@ public class DayPicker extends FrameLayout { * @param endRangeDate The end date. */ public void setRange(Calendar startRangeDate, Calendar endRangeDate) { - boolean doSetupAdapter = false; + boolean rangeChanged = false; if (mRangeStartDate.get(Calendar.DAY_OF_YEAR) != startRangeDate.get(Calendar.DAY_OF_YEAR) || mRangeStartDate.get(Calendar.YEAR) != startRangeDate.get(Calendar.YEAR)) { mRangeStartDate.setTimeInMillis(startRangeDate.getTimeInMillis()); mRangeStartDate.setTimeZone(startRangeDate.getTimeZone()); - doSetupAdapter = true; + rangeChanged = true; } if (mRangeEndDate.get(Calendar.DAY_OF_YEAR) != endRangeDate.get(Calendar.DAY_OF_YEAR) || mRangeEndDate.get(Calendar.YEAR) != endRangeDate.get(Calendar.YEAR)) { mRangeEndDate.setTimeInMillis(endRangeDate.getTimeInMillis()); mRangeEndDate.setTimeZone(endRangeDate.getTimeZone()); - doSetupAdapter = true; - + rangeChanged = true; } - if (doSetupAdapter) { - setUpAdapter(); + + if (!rangeChanged) { + return; + } + + // now recreate the adapter since we have a new range to handle + mAdapter = null; + setUpAdapter(); + + // set the current date to today if in the range + // otherwise to the closest end of the range + mTempCalendar.clear(); + mTempCalendar.setTimeInMillis(System.currentTimeMillis()); + if (mTempCalendar.before(mRangeStartDate)) { + goTo(mRangeStartDate, false, true, true); + } else if (mTempCalendar.after(mRangeEndDate)) { + goTo(mRangeEndDate, false, true, true); + } else { + goTo(mTempCalendar, false, true, true); } } @@ -629,7 +645,6 @@ public class DayPicker extends FrameLayout { } // Figure out where we are - int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0; long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom(); // If we have moved since our last call update the direction @@ -645,6 +660,7 @@ public class DayPicker extends FrameLayout { // causes the month to transition when two full weeks of a month are // visible when scrolling up, and when the first day in a month reaches // the top of the screen when scrolling down. + int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0; if (mIsScrollingUp) { child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset); } else if (offset != 0) { @@ -712,8 +728,9 @@ public class DayPicker extends FrameLayout { throw new IllegalArgumentException("fromDate: " + mRangeStartDate.getTime() + " does not precede toDate: " + toDate.getTime()); } + int fromDateDayOfWeek = mRangeStartDate.get(Calendar.DAY_OF_WEEK); - long diff = (fromDateDayOfWeek - toDate.getFirstDayOfWeek()) * MILLIS_IN_DAY; + long diff = (fromDateDayOfWeek - mFirstDayOfWeek) * MILLIS_IN_DAY; if (diff < 0) { diff = diff + MILLIS_IN_WEEK; } @@ -874,7 +891,16 @@ public class DayPicker extends FrameLayout { protected void init() { mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener()); mSelectedWeek = getWeeksDelta(mSelectedDay); - mTotalWeekCount = getWeeksDelta(mRangeEndDate); + + // make adjustment to fit the range last week with needed overflow + mTempCalendar.setTimeInMillis(mRangeEndDate.getTimeInMillis()); + mTempCalendar.setTimeZone(mRangeEndDate.getTimeZone()); + int diff = mFirstDayOfWeek - mRangeEndDate.get(Calendar.DAY_OF_WEEK); + if (diff < 0) { + diff += DAYS_PER_WEEK; + } + mTempCalendar.add(Calendar.DAY_OF_WEEK, diff); + mTotalWeekCount = getWeeksDelta(mTempCalendar); } /** @@ -892,7 +918,6 @@ public class DayPicker extends FrameLayout { mSelectedWeek = getWeeksDelta(mSelectedDay); mFocusMonth = mSelectedDay.get(Calendar.MONTH); notifyDataSetChanged(); - invalidate(); // Test } /** @@ -1004,9 +1029,12 @@ public class DayPicker extends FrameLayout { if (mGestureDetector.onTouchEvent(event)) { WeekView weekView = (WeekView) v; weekView.getDayFromLocation(event.getX(), mTempCalendar); - if (mTempCalendar.get(Calendar.YEAR) != 0) { - onDayTapped(mTempCalendar); + // it is possible that the touched day is outside the valid range + // we draw whole weeks but range end can fall not on the week end + if (mTempCalendar.before(mRangeStartDate) || mTempCalendar.after(mRangeEndDate)) { + return true; } + onDayTapped(mTempCalendar); return true; } return false; @@ -1019,6 +1047,7 @@ public class DayPicker extends FrameLayout { */ protected void onDayTapped(Calendar day) { setSelectedDay(day); + setMonthDisplayed(day); } /** @@ -1244,8 +1273,8 @@ public class DayPicker extends FrameLayout { mNumCells = mShowWeekNumber ? mWeekDayCount + 1 : mWeekDayCount; } mWeek = ((int[]) params.get(VIEW_PARAMS_WEEK))[0]; - mTempCalendar.clear(); - mTempCalendar.set(1900, 0, 1); + mTempCalendar.setTimeInMillis(mRangeStartDate.getTimeInMillis()); + mTempCalendar.setTimeZone(mRangeStartDate.getTimeZone()); mTempCalendar.add(Calendar.WEEK_OF_YEAR, mWeek); if (params.containsKey(VIEW_PARAMS_WEEK_START)) { mTempCalendar.setFirstDayOfWeek(((int[]) params.get(VIEW_PARAMS_WEEK_START))[0]); @@ -1277,7 +1306,12 @@ public class DayPicker extends FrameLayout { for (; i < mNumCells; i++) { mFocusDay[i] = (mTempCalendar.get(Calendar.MONTH) == focusMonth); - mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH)); + // do not draw dates outside the valid range to avoid user confusion + if (mTempCalendar.before(mRangeStartDate) || mTempCalendar.after(mRangeEndDate)) { + mDayNumbers[i] = ""; + } else { + mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH)); + } mTempCalendar.add(Calendar.DAY_OF_MONTH, 1); } // We do one extra add at the end of the loop, if that pushed us to diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 8c22f9771864..a236d27c616e 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1189,9 +1189,9 @@ public class NumberPicker extends LinearLayout { */ private int getWrappedSelectorIndex(int selectorIndex) { if (selectorIndex > mEnd) { - return mStart + (selectorIndex - mEnd) % (mEnd - mStart); + return mStart + (selectorIndex - mEnd) % (mEnd - mStart) - 1; } else if (selectorIndex < mStart) { - return mEnd - (mStart - selectorIndex) % (mEnd - mStart); + return mEnd - (mStart - selectorIndex) % (mEnd - mStart) + 1; } return selectorIndex; } -- cgit v1.2.3-59-g8ed1b