2 * Copyright (C) 2014 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.widget;
19 import android.content.Context;
20 import android.content.res.ColorStateList;
21 import android.content.res.Configuration;
22 import android.content.res.Resources;
23 import android.content.res.TypedArray;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.text.format.DateFormat;
27 import android.text.format.DateUtils;
28 import android.util.AttributeSet;
29 import android.view.HapticFeedbackConstants;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.accessibility.AccessibilityEvent;
33 import android.view.accessibility.AccessibilityNodeInfo;
34 import android.view.animation.AlphaAnimation;
35 import android.view.animation.Animation;
37 import com.android.internal.R;
38 import com.android.internal.widget.AccessibleDateAnimator;
40 import java.text.SimpleDateFormat;
41 import java.util.Calendar;
42 import java.util.HashSet;
43 import java.util.Locale;
46 * A delegate for picking up a date (day / month / year).
48 class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements
49 View.OnClickListener, DatePickerController {
50 private static final int USE_LOCALE = 0;
52 private static final int UNINITIALIZED = -1;
53 private static final int MONTH_AND_DAY_VIEW = 0;
54 private static final int YEAR_VIEW = 1;
56 private static final int DEFAULT_START_YEAR = 1900;
57 private static final int DEFAULT_END_YEAR = 2100;
59 private static final int ANIMATION_DURATION = 300;
61 private static final int MONTH_INDEX = 0;
62 private static final int DAY_INDEX = 1;
63 private static final int YEAR_INDEX = 2;
65 private SimpleDateFormat mYearFormat = new SimpleDateFormat("y", Locale.getDefault());
66 private SimpleDateFormat mDayFormat = new SimpleDateFormat("d", Locale.getDefault());
68 private TextView mDayOfWeekView;
70 /** Layout that contains the current month, day, and year. */
71 private LinearLayout mMonthDayYearLayout;
73 /** Clickable layout that contains the current day and year. */
74 private LinearLayout mMonthAndDayLayout;
76 private TextView mHeaderMonthTextView;
77 private TextView mHeaderDayOfMonthTextView;
78 private TextView mHeaderYearTextView;
79 private DayPickerView mDayPickerView;
80 private YearPickerView mYearPickerView;
82 private boolean mIsEnabled = true;
84 // Accessibility strings.
85 private String mDayPickerDescription;
86 private String mSelectDay;
87 private String mYearPickerDescription;
88 private String mSelectYear;
90 private AccessibleDateAnimator mAnimator;
92 private DatePicker.OnDateChangedListener mDateChangedListener;
94 private int mCurrentView = UNINITIALIZED;
96 private Calendar mCurrentDate;
97 private Calendar mTempDate;
98 private Calendar mMinDate;
99 private Calendar mMaxDate;
101 private int mFirstDayOfWeek = USE_LOCALE;
103 private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
105 public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
106 int defStyleAttr, int defStyleRes) {
107 super(delegator, context);
109 final Locale locale = Locale.getDefault();
110 mMinDate = getCalendarForLocale(mMinDate, locale);
111 mMaxDate = getCalendarForLocale(mMaxDate, locale);
112 mTempDate = getCalendarForLocale(mMaxDate, locale);
113 mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
115 mMinDate.set(DEFAULT_START_YEAR, 1, 1);
116 mMaxDate.set(DEFAULT_END_YEAR, 12, 31);
118 final Resources res = mDelegator.getResources();
119 final TypedArray a = mContext.obtainStyledAttributes(attrs,
120 R.styleable.DatePicker, defStyleAttr, defStyleRes);
121 final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
122 Context.LAYOUT_INFLATER_SERVICE);
123 final int layoutResourceId = a.getResourceId(
124 R.styleable.DatePicker_internalLayout, R.layout.date_picker_holo);
125 final View mainView = inflater.inflate(layoutResourceId, null);
126 mDelegator.addView(mainView);
128 mDayOfWeekView = (TextView) mainView.findViewById(R.id.date_picker_header);
130 // Layout that contains the current date and day name header.
131 final LinearLayout dateLayout = (LinearLayout) mainView.findViewById(
132 R.id.day_picker_selector_layout);
133 mMonthDayYearLayout = (LinearLayout) mainView.findViewById(
134 R.id.date_picker_month_day_year_layout);
135 mMonthAndDayLayout = (LinearLayout) mainView.findViewById(
136 R.id.date_picker_month_and_day_layout);
137 mMonthAndDayLayout.setOnClickListener(this);
138 mHeaderMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_month);
139 mHeaderDayOfMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_day);
140 mHeaderYearTextView = (TextView) mainView.findViewById(R.id.date_picker_year);
141 mHeaderYearTextView.setOnClickListener(this);
143 // Obtain default highlight color from the theme.
144 final int defaultHighlightColor = mHeaderYearTextView.getHighlightColor();
146 // Use Theme attributes if possible
147 final int dayOfWeekTextAppearanceResId = a.getResourceId(
148 R.styleable.DatePicker_dayOfWeekTextAppearance, -1);
149 if (dayOfWeekTextAppearanceResId != -1) {
150 mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId);
153 mDayOfWeekView.setBackground(a.getDrawable(R.styleable.DatePicker_dayOfWeekBackground));
155 dateLayout.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
157 final int headerSelectedTextColor = a.getColor(
158 R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor);
159 final int monthTextAppearanceResId = a.getResourceId(
160 R.styleable.DatePicker_headerMonthTextAppearance, -1);
161 if (monthTextAppearanceResId != -1) {
162 mHeaderMonthTextView.setTextAppearance(context, monthTextAppearanceResId);
164 mHeaderMonthTextView.setTextColor(ColorStateList.addFirstIfMissing(
165 mHeaderMonthTextView.getTextColors(), R.attr.state_selected,
166 headerSelectedTextColor));
168 final int dayOfMonthTextAppearanceResId = a.getResourceId(
169 R.styleable.DatePicker_headerDayOfMonthTextAppearance, -1);
170 if (dayOfMonthTextAppearanceResId != -1) {
171 mHeaderDayOfMonthTextView.setTextAppearance(context, dayOfMonthTextAppearanceResId);
173 mHeaderDayOfMonthTextView.setTextColor(ColorStateList.addFirstIfMissing(
174 mHeaderDayOfMonthTextView.getTextColors(), R.attr.state_selected,
175 headerSelectedTextColor));
177 final int yearTextAppearanceResId = a.getResourceId(
178 R.styleable.DatePicker_headerYearTextAppearance, -1);
179 if (yearTextAppearanceResId != -1) {
180 mHeaderYearTextView.setTextAppearance(context, yearTextAppearanceResId);
182 mHeaderYearTextView.setTextColor(ColorStateList.addFirstIfMissing(
183 mHeaderYearTextView.getTextColors(), R.attr.state_selected,
184 headerSelectedTextColor));
186 mDayPickerView = new DayPickerView(mContext);
187 mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
188 mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
189 mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
190 mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
191 mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
193 mYearPickerView = new YearPickerView(mContext);
194 mYearPickerView.init(this);
196 final int yearSelectedCircleColor = a.getColor(R.styleable.DatePicker_yearListSelectorColor,
197 defaultHighlightColor);
198 mYearPickerView.setYearSelectedCircleColor(yearSelectedCircleColor);
200 final ColorStateList calendarTextColor = a.getColorStateList(
201 R.styleable.DatePicker_calendarTextColor);
202 final int calendarSelectedTextColor = a.getColor(
203 R.styleable.DatePicker_calendarSelectedTextColor, defaultHighlightColor);
204 mDayPickerView.setCalendarTextColor(ColorStateList.addFirstIfMissing(
205 calendarTextColor, R.attr.state_selected, calendarSelectedTextColor));
207 mDayPickerDescription = res.getString(R.string.day_picker_description);
208 mSelectDay = res.getString(R.string.select_day);
209 mYearPickerDescription = res.getString(R.string.year_picker_description);
210 mSelectYear = res.getString(R.string.select_year);
212 mAnimator = (AccessibleDateAnimator) mainView.findViewById(R.id.animator);
213 mAnimator.addView(mDayPickerView);
214 mAnimator.addView(mYearPickerView);
215 mAnimator.setDateMillis(mCurrentDate.getTimeInMillis());
217 final Animation animation = new AlphaAnimation(0.0f, 1.0f);
218 animation.setDuration(ANIMATION_DURATION);
219 mAnimator.setInAnimation(animation);
221 final Animation animation2 = new AlphaAnimation(1.0f, 0.0f);
222 animation2.setDuration(ANIMATION_DURATION);
223 mAnimator.setOutAnimation(animation2);
225 updateDisplay(false);
226 setCurrentView(MONTH_AND_DAY_VIEW);
230 * Gets a calendar for locale bootstrapped with the value of a given calendar.
232 * @param oldCalendar The old calendar.
233 * @param locale The locale.
235 private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
236 if (oldCalendar == null) {
237 return Calendar.getInstance(locale);
239 final long currentTimeMillis = oldCalendar.getTimeInMillis();
240 Calendar newCalendar = Calendar.getInstance(locale);
241 newCalendar.setTimeInMillis(currentTimeMillis);
247 * Compute the array representing the order of Month / Day / Year views in their layout.
248 * Will be used for I18N purpose as the order of them depends on the Locale.
250 private int[] getMonthDayYearIndexes(String pattern) {
251 int[] result = new int[3];
253 final String filteredPattern = pattern.replaceAll("'.*?'", "");
255 final int dayIndex = filteredPattern.indexOf('d');
256 final int monthMIndex = filteredPattern.indexOf("M");
257 final int monthIndex = (monthMIndex != -1) ? monthMIndex : filteredPattern.indexOf("L");
258 final int yearIndex = filteredPattern.indexOf("y");
260 if (yearIndex < monthIndex) {
261 result[YEAR_INDEX] = 0;
263 if (monthIndex < dayIndex) {
264 result[MONTH_INDEX] = 1;
265 result[DAY_INDEX] = 2;
267 result[MONTH_INDEX] = 2;
268 result[DAY_INDEX] = 1;
271 result[YEAR_INDEX] = 2;
273 if (monthIndex < dayIndex) {
274 result[MONTH_INDEX] = 0;
275 result[DAY_INDEX] = 1;
277 result[MONTH_INDEX] = 1;
278 result[DAY_INDEX] = 0;
284 private void updateDisplay(boolean announce) {
285 if (mDayOfWeekView != null) {
286 mDayOfWeekView.setText(mCurrentDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG,
287 Locale.getDefault()));
290 // Compute indices of Month, Day and Year views
291 final String bestDateTimePattern =
292 DateFormat.getBestDateTimePattern(mCurrentLocale, "yMMMd");
293 final int[] viewIndices = getMonthDayYearIndexes(bestDateTimePattern);
295 // Position the Year and MonthAndDay views within the header.
296 mMonthDayYearLayout.removeAllViews();
297 if (viewIndices[YEAR_INDEX] == 0) {
298 mMonthDayYearLayout.addView(mHeaderYearTextView);
299 mMonthDayYearLayout.addView(mMonthAndDayLayout);
301 mMonthDayYearLayout.addView(mMonthAndDayLayout);
302 mMonthDayYearLayout.addView(mHeaderYearTextView);
305 // Position Day and Month views within the MonthAndDay view.
306 mMonthAndDayLayout.removeAllViews();
307 if (viewIndices[MONTH_INDEX] > viewIndices[DAY_INDEX]) {
308 mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView);
309 mMonthAndDayLayout.addView(mHeaderMonthTextView);
311 mMonthAndDayLayout.addView(mHeaderMonthTextView);
312 mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView);
315 mHeaderMonthTextView.setText(mCurrentDate.getDisplayName(Calendar.MONTH, Calendar.SHORT,
316 Locale.getDefault()).toUpperCase(Locale.getDefault()));
317 mHeaderDayOfMonthTextView.setText(mDayFormat.format(mCurrentDate.getTime()));
318 mHeaderYearTextView.setText(mYearFormat.format(mCurrentDate.getTime()));
321 long millis = mCurrentDate.getTimeInMillis();
322 mAnimator.setDateMillis(millis);
323 int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
324 String monthAndDayText = DateUtils.formatDateTime(mContext, millis, flags);
325 mMonthAndDayLayout.setContentDescription(monthAndDayText);
328 flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
329 String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
330 mAnimator.announceForAccessibility(fullDateText);
334 private void setCurrentView(final int viewIndex) {
335 long millis = mCurrentDate.getTimeInMillis();
338 case MONTH_AND_DAY_VIEW:
339 mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
340 if (mCurrentView != viewIndex) {
341 mMonthAndDayLayout.setSelected(true);
342 mHeaderYearTextView.setSelected(false);
343 mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
344 mCurrentView = viewIndex;
347 final int flags = DateUtils.FORMAT_SHOW_DATE;
348 final String dayString = DateUtils.formatDateTime(mContext, millis, flags);
349 mAnimator.setContentDescription(mDayPickerDescription + ": " + dayString);
350 mAnimator.announceForAccessibility(mSelectDay);
353 mYearPickerView.onDateChanged();
354 if (mCurrentView != viewIndex) {
355 mMonthAndDayLayout.setSelected(false);
356 mHeaderYearTextView.setSelected(true);
357 mAnimator.setDisplayedChild(YEAR_VIEW);
358 mCurrentView = viewIndex;
361 final CharSequence yearString = mYearFormat.format(millis);
362 mAnimator.setContentDescription(mYearPickerDescription + ": " + yearString);
363 mAnimator.announceForAccessibility(mSelectYear);
369 public void init(int year, int monthOfYear, int dayOfMonth,
370 DatePicker.OnDateChangedListener callBack) {
371 mCurrentDate.set(Calendar.YEAR, year);
372 mCurrentDate.set(Calendar.MONTH, monthOfYear);
373 mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
375 mDateChangedListener = callBack;
377 onDateChanged(false, false);
381 public void updateDate(int year, int month, int dayOfMonth) {
382 mCurrentDate.set(Calendar.YEAR, year);
383 mCurrentDate.set(Calendar.MONTH, month);
384 mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
386 onDateChanged(false, true);
389 private void onDateChanged(boolean fromUser, boolean callbackToClient) {
390 if (callbackToClient && mDateChangedListener != null) {
391 final int year = mCurrentDate.get(Calendar.YEAR);
392 final int monthOfYear = mCurrentDate.get(Calendar.MONTH);
393 final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
394 mDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
397 for (OnDateChangedListener listener : mListeners) {
398 listener.onDateChanged();
401 mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
403 updateDisplay(fromUser);
411 public int getYear() {
412 return mCurrentDate.get(Calendar.YEAR);
416 public int getMonth() {
417 return mCurrentDate.get(Calendar.MONTH);
421 public int getDayOfMonth() {
422 return mCurrentDate.get(Calendar.DAY_OF_MONTH);
426 public void setMinDate(long minDate) {
427 mTempDate.setTimeInMillis(minDate);
428 if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
429 && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
432 if (mCurrentDate.before(mTempDate)) {
433 mCurrentDate.setTimeInMillis(minDate);
434 onDateChanged(false, true);
436 mMinDate.setTimeInMillis(minDate);
437 mDayPickerView.setMinDate(minDate);
438 mYearPickerView.setRange(mMinDate, mMaxDate);
442 public Calendar getMinDate() {
447 public void setMaxDate(long maxDate) {
448 mTempDate.setTimeInMillis(maxDate);
449 if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
450 && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
453 if (mCurrentDate.after(mTempDate)) {
454 mCurrentDate.setTimeInMillis(maxDate);
455 onDateChanged(false, true);
457 mMaxDate.setTimeInMillis(maxDate);
458 mDayPickerView.setMaxDate(maxDate);
459 mYearPickerView.setRange(mMinDate, mMaxDate);
463 public Calendar getMaxDate() {
468 public void setFirstDayOfWeek(int firstDayOfWeek) {
469 mFirstDayOfWeek = firstDayOfWeek;
471 mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
475 public int getFirstDayOfWeek() {
476 if (mFirstDayOfWeek != USE_LOCALE) {
477 return mFirstDayOfWeek;
479 return mCurrentDate.getFirstDayOfWeek();
483 public void setEnabled(boolean enabled) {
484 mMonthAndDayLayout.setEnabled(enabled);
485 mHeaderYearTextView.setEnabled(enabled);
486 mAnimator.setEnabled(enabled);
487 mIsEnabled = enabled;
491 public boolean isEnabled() {
496 public CalendarView getCalendarView() {
497 throw new UnsupportedOperationException(
498 "CalendarView does not exists for the new DatePicker");
502 public void setCalendarViewShown(boolean shown) {
503 // No-op for compatibility with the old DatePicker.
507 public boolean getCalendarViewShown() {
512 public void setSpinnersShown(boolean shown) {
513 // No-op for compatibility with the old DatePicker.
517 public boolean getSpinnersShown() {
522 public void onConfigurationChanged(Configuration newConfig) {
523 mYearFormat = new SimpleDateFormat("y", newConfig.locale);
524 mDayFormat = new SimpleDateFormat("d", newConfig.locale);
528 public Parcelable onSaveInstanceState(Parcelable superState) {
529 final int year = mCurrentDate.get(Calendar.YEAR);
530 final int month = mCurrentDate.get(Calendar.MONTH);
531 final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
533 int listPosition = -1;
534 int listPositionOffset = -1;
536 if (mCurrentView == MONTH_AND_DAY_VIEW) {
537 listPosition = mDayPickerView.getMostVisiblePosition();
538 } else if (mCurrentView == YEAR_VIEW) {
539 listPosition = mYearPickerView.getFirstVisiblePosition();
540 listPositionOffset = mYearPickerView.getFirstPositionOffset();
543 return new SavedState(superState, year, month, day, mMinDate.getTimeInMillis(),
544 mMaxDate.getTimeInMillis(), mCurrentView, listPosition, listPositionOffset);
548 public void onRestoreInstanceState(Parcelable state) {
549 SavedState ss = (SavedState) state;
551 mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
552 mCurrentView = ss.getCurrentView();
553 mMinDate.setTimeInMillis(ss.getMinDate());
554 mMaxDate.setTimeInMillis(ss.getMaxDate());
556 updateDisplay(false);
557 setCurrentView(mCurrentView);
559 final int listPosition = ss.getListPosition();
560 if (listPosition != -1) {
561 if (mCurrentView == MONTH_AND_DAY_VIEW) {
562 mDayPickerView.postSetSelection(listPosition);
563 } else if (mCurrentView == YEAR_VIEW) {
564 mYearPickerView.postSetSelectionFromTop(listPosition, ss.getListPositionOffset());
570 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
571 onPopulateAccessibilityEvent(event);
576 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
577 event.getText().add(mCurrentDate.getTime().toString());
581 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
582 event.setClassName(DatePicker.class.getName());
586 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
587 info.setClassName(DatePicker.class.getName());
591 public void onYearSelected(int year) {
592 adjustDayInMonthIfNeeded(mCurrentDate.get(Calendar.MONTH), year);
593 mCurrentDate.set(Calendar.YEAR, year);
594 onDateChanged(true, true);
596 // Auto-advance to month and day view.
597 setCurrentView(MONTH_AND_DAY_VIEW);
600 // If the newly selected month / year does not contain the currently selected day number,
601 // change the selected day number to the last day of the selected month or year.
602 // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
603 // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
604 private void adjustDayInMonthIfNeeded(int month, int year) {
605 int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
606 int daysInMonth = getDaysInMonth(month, year);
607 if (day > daysInMonth) {
608 mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth);
612 public static int getDaysInMonth(int month, int year) {
614 case Calendar.JANUARY:
618 case Calendar.AUGUST:
619 case Calendar.OCTOBER:
620 case Calendar.DECEMBER:
624 case Calendar.SEPTEMBER:
625 case Calendar.NOVEMBER:
627 case Calendar.FEBRUARY:
628 return (year % 4 == 0) ? 29 : 28;
630 throw new IllegalArgumentException("Invalid Month");
635 public void registerOnDateChangedListener(OnDateChangedListener listener) {
636 mListeners.add(listener);
640 public Calendar getSelectedDay() {
645 public void tryVibrate() {
646 mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
650 public void onClick(View v) {
652 if (v.getId() == R.id.date_picker_year) {
653 setCurrentView(YEAR_VIEW);
654 } else if (v.getId() == R.id.date_picker_month_and_day_layout) {
655 setCurrentView(MONTH_AND_DAY_VIEW);
660 * Listener called when the user selects a day in the day picker view.
662 private final DayPickerView.OnDaySelectedListener
663 mOnDaySelectedListener = new DayPickerView.OnDaySelectedListener() {
665 public void onDaySelected(DayPickerView view, Calendar day) {
666 mCurrentDate.setTimeInMillis(day.getTimeInMillis());
667 onDateChanged(true, true);
672 * Class for managing state storing/restoring.
674 private static class SavedState extends View.BaseSavedState {
676 private final int mSelectedYear;
677 private final int mSelectedMonth;
678 private final int mSelectedDay;
679 private final long mMinDate;
680 private final long mMaxDate;
681 private final int mCurrentView;
682 private final int mListPosition;
683 private final int mListPositionOffset;
686 * Constructor called from {@link DatePicker#onSaveInstanceState()}
688 private SavedState(Parcelable superState, int year, int month, int day,
689 long minDate, long maxDate, int currentView, int listPosition,
690 int listPositionOffset) {
692 mSelectedYear = year;
693 mSelectedMonth = month;
697 mCurrentView = currentView;
698 mListPosition = listPosition;
699 mListPositionOffset = listPositionOffset;
703 * Constructor called from {@link #CREATOR}
705 private SavedState(Parcel in) {
707 mSelectedYear = in.readInt();
708 mSelectedMonth = in.readInt();
709 mSelectedDay = in.readInt();
710 mMinDate = in.readLong();
711 mMaxDate = in.readLong();
712 mCurrentView = in.readInt();
713 mListPosition = in.readInt();
714 mListPositionOffset = in.readInt();
718 public void writeToParcel(Parcel dest, int flags) {
719 super.writeToParcel(dest, flags);
720 dest.writeInt(mSelectedYear);
721 dest.writeInt(mSelectedMonth);
722 dest.writeInt(mSelectedDay);
723 dest.writeLong(mMinDate);
724 dest.writeLong(mMaxDate);
725 dest.writeInt(mCurrentView);
726 dest.writeInt(mListPosition);
727 dest.writeInt(mListPositionOffset);
730 public int getSelectedDay() {
734 public int getSelectedMonth() {
735 return mSelectedMonth;
738 public int getSelectedYear() {
739 return mSelectedYear;
742 public long getMinDate() {
746 public long getMaxDate() {
750 public int getCurrentView() {
754 public int getListPosition() {
755 return mListPosition;
758 public int getListPositionOffset() {
759 return mListPositionOffset;
762 @SuppressWarnings("all")
763 // suppress unused and hiding
764 public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
766 public SavedState createFromParcel(Parcel in) {
767 return new SavedState(in);
770 public SavedState[] newArray(int size) {
771 return new SavedState[size];