blob: 90486b72860b586e84e646cb9ac92fa42a0708ac [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package android.widget;
18
19import android.annotation.Widget;
20import android.content.Context;
Svetoslav Ganovf5926962011-07-12 12:26:20 -070021import android.content.res.Configuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.res.TypedArray;
23import android.os.Parcel;
24import android.os.Parcelable;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080025import android.text.TextUtils;
Hyejin Kime9a74a12013-03-20 18:14:00 +090026import android.text.InputType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.text.format.DateFormat;
Kenny Rootdddda8d2010-11-15 14:38:51 -080028import android.text.format.DateUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.util.AttributeSet;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080030import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.util.SparseArray;
32import android.view.LayoutInflater;
Svetoslav Ganovd11e6152012-03-20 12:13:02 -070033import android.view.View;
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -080034import android.view.accessibility.AccessibilityEvent;
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -080035import android.view.accessibility.AccessibilityNodeInfo;
Svetoslav Ganova53efe92011-09-08 18:08:36 -070036import android.view.inputmethod.EditorInfo;
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -070037import android.view.inputmethod.InputMethodManager;
Svetoslav Ganovcedc4462011-01-19 19:25:46 -080038import android.widget.NumberPicker.OnValueChangeListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
Svetoslav Ganovf5926962011-07-12 12:26:20 -070040import com.android.internal.R;
41
Elliott Hughes949e9df2013-04-30 13:41:06 -070042import java.text.DateFormatSymbols;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080043import java.text.ParseException;
Eric Fischer03a80172009-07-23 18:32:42 -070044import java.text.SimpleDateFormat;
Svetoslav Ganov156f2092011-01-24 02:13:36 -080045import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import java.util.Calendar;
Kenny Rootdddda8d2010-11-15 14:38:51 -080047import java.util.Locale;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080048import java.util.TimeZone;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
Elliott Hughes659f1452013-04-30 11:11:53 -070050import libcore.icu.ICU;
51
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052/**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080053 * This class is a widget for selecting a date. The date can be selected by a
54 * year, month, and day spinners or a {@link CalendarView}. The set of spinners
55 * and the calendar view are automatically synchronized. The client can
56 * customize whether only the spinners, or only the calendar view, or both to be
57 * displayed. Also the minimal and maximal date from which dates to be selected
58 * can be customized.
Svetoslav Ganov50f34d12010-12-03 16:05:40 -080059 * <p>
Scott Main4c359b72012-07-24 15:51:27 -070060 * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
61 * guide.
Svetoslav Ganov50f34d12010-12-03 16:05:40 -080062 * </p>
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080063 * <p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 * For a dialog using this view, see {@link android.app.DatePickerDialog}.
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080065 * </p>
66 *
67 * @attr ref android.R.styleable#DatePicker_startYear
68 * @attr ref android.R.styleable#DatePicker_endYear
69 * @attr ref android.R.styleable#DatePicker_maxDate
70 * @attr ref android.R.styleable#DatePicker_minDate
71 * @attr ref android.R.styleable#DatePicker_spinnersShown
72 * @attr ref android.R.styleable#DatePicker_calendarViewShown
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 */
74@Widget
75public class DatePicker extends FrameLayout {
76
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080077 private static final String LOG_TAG = DatePicker.class.getSimpleName();
78
79 private static final String DATE_FORMAT = "MM/dd/yyyy";
80
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 private static final int DEFAULT_START_YEAR = 1900;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -080082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private static final int DEFAULT_END_YEAR = 2100;
Kenny Rootdddda8d2010-11-15 14:38:51 -080084
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080085 private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -080086
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080087 private static final boolean DEFAULT_SPINNERS_SHOWN = true;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -080088
Svetoslav Ganov25f84f32010-12-29 22:39:54 -080089 private static final boolean DEFAULT_ENABLED_STATE = true;
90
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080091 private final LinearLayout mSpinners;
92
Svetoslav Ganova53efe92011-09-08 18:08:36 -070093 private final NumberPicker mDaySpinner;
94
Svetoslav Ganove9730bf2010-12-20 21:25:20 -080095 private final NumberPicker mMonthSpinner;
96
97 private final NumberPicker mYearSpinner;
98
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -070099 private final EditText mDaySpinnerInput;
100
101 private final EditText mMonthSpinnerInput;
102
103 private final EditText mYearSpinnerInput;
104
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800105 private final CalendarView mCalendarView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700107 private Locale mCurrentLocale;
108
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800109 private OnDateChangedListener mOnDateChangedListener;
110
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700111 private String[] mShortMonths;
Kenny Rootdddda8d2010-11-15 14:38:51 -0800112
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800113 private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
114
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700115 private int mNumberOfMonths;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800116
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700117 private Calendar mTempDate;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800118
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700119 private Calendar mMinDate;
120
121 private Calendar mMaxDate;
122
123 private Calendar mCurrentDate;
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800124
Svetoslav Ganov25f84f32010-12-29 22:39:54 -0800125 private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
Svetoslav Ganov51c52ed2010-12-28 13:45:03 -0800126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800128 * The callback used to indicate the user changes\d the date.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 */
130 public interface OnDateChangedListener {
131
132 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800133 * Called upon a date change.
134 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 * @param view The view associated with this listener.
136 * @param year The year that was set.
137 * @param monthOfYear The month that was set (0-11) for compatibility
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800138 * with {@link java.util.Calendar}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 * @param dayOfMonth The day of the month that was set.
140 */
141 void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
142 }
143
144 public DatePicker(Context context) {
145 this(context, null);
146 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 public DatePicker(Context context, AttributeSet attrs) {
Svetoslav Ganov4243dc32011-01-18 19:39:57 -0800149 this(context, attrs, R.attr.datePickerStyle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 }
151
Alan Viverette617feb92013-09-09 18:09:13 -0700152 public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) {
153 this(context, attrs, defStyleAttr, 0);
154 }
155
156 public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
157 super(context, attrs, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700159 // initialization based on locale
160 setCurrentLocale(Locale.getDefault());
161
Alan Viverette617feb92013-09-09 18:09:13 -0700162 final TypedArray attributesArray = context.obtainStyledAttributes(
163 attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800164 boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
165 DEFAULT_SPINNERS_SHOWN);
166 boolean calendarViewShown = attributesArray.getBoolean(
167 R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
Svetoslav Ganov4243dc32011-01-18 19:39:57 -0800168 int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear,
169 DEFAULT_START_YEAR);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800170 int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
171 String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
172 String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
Svetoslav Ganovc49a8be2012-03-02 13:39:25 -0800173 int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_internalLayout,
Svetoslav Ganov4243dc32011-01-18 19:39:57 -0800174 R.layout.date_picker);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800175 attributesArray.recycle();
176
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800177 LayoutInflater inflater = (LayoutInflater) context
178 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Svetoslav Ganov4243dc32011-01-18 19:39:57 -0800179 inflater.inflate(layoutResourceId, this, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180
Svetoslav Ganovcedc4462011-01-19 19:25:46 -0800181 OnValueChangeListener onChangeListener = new OnValueChangeListener() {
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800182 public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -0700183 updateInputState();
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800184 mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
185 // take care of wrapping of days and months to update greater fields
186 if (picker == mDaySpinner) {
187 int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
188 if (oldVal == maxDayOfMonth && newVal == 1) {
189 mTempDate.add(Calendar.DAY_OF_MONTH, 1);
190 } else if (oldVal == 1 && newVal == maxDayOfMonth) {
191 mTempDate.add(Calendar.DAY_OF_MONTH, -1);
192 } else {
193 mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
194 }
195 } else if (picker == mMonthSpinner) {
196 if (oldVal == 11 && newVal == 0) {
197 mTempDate.add(Calendar.MONTH, 1);
198 } else if (oldVal == 0 && newVal == 11) {
199 mTempDate.add(Calendar.MONTH, -1);
200 } else {
201 mTempDate.add(Calendar.MONTH, newVal - oldVal);
202 }
203 } else if (picker == mYearSpinner) {
204 mTempDate.set(Calendar.YEAR, newVal);
205 } else {
206 throw new IllegalArgumentException();
207 }
208 // now set the date to the adjusted one
209 setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
210 mTempDate.get(Calendar.DAY_OF_MONTH));
Svetoslav Ganov58f51252011-01-26 22:50:51 -0800211 updateSpinners();
212 updateCalendarView();
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800213 notifyDateChanged();
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800214 }
215 };
216
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800217 mSpinners = (LinearLayout) findViewById(R.id.pickers);
218
219 // calendar view day-picker
220 mCalendarView = (CalendarView) findViewById(R.id.calendar_view);
221 mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
222 public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800223 setDate(year, month, monthDay);
Svetoslav Ganov58f51252011-01-26 22:50:51 -0800224 updateSpinners();
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800225 notifyDateChanged();
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800226 }
227 });
228
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800229 // day
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800230 mDaySpinner = (NumberPicker) findViewById(R.id.day);
Fabrice Di Megliod88e3052012-09-21 12:15:23 -0700231 mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800232 mDaySpinner.setOnLongPressUpdateInterval(100);
233 mDaySpinner.setOnValueChangedListener(onChangeListener);
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -0700234 mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800235
236 // month
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800237 mMonthSpinner = (NumberPicker) findViewById(R.id.month);
238 mMonthSpinner.setMinValue(0);
239 mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700240 mMonthSpinner.setDisplayedValues(mShortMonths);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800241 mMonthSpinner.setOnLongPressUpdateInterval(200);
242 mMonthSpinner.setOnValueChangedListener(onChangeListener);
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -0700243 mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800244
245 // year
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800246 mYearSpinner = (NumberPicker) findViewById(R.id.year);
247 mYearSpinner.setOnLongPressUpdateInterval(100);
248 mYearSpinner.setOnValueChangedListener(onChangeListener);
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -0700249 mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800250
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800251 // show only what the user required but make sure we
252 // show something and the spinners have higher priority
253 if (!spinnersShown && !calendarViewShown) {
254 setSpinnersShown(true);
255 } else {
256 setSpinnersShown(spinnersShown);
257 setCalendarViewShown(calendarViewShown);
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800258 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800259
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800260 // set the min date giving priority of the minDate over startYear
261 mTempDate.clear();
262 if (!TextUtils.isEmpty(minDate)) {
263 if (!parseDate(minDate, mTempDate)) {
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800264 mTempDate.set(startYear, 0, 1);
265 }
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800266 } else {
267 mTempDate.set(startYear, 0, 1);
268 }
269 setMinDate(mTempDate.getTimeInMillis());
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800270
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800271 // set the max date giving priority of the maxDate over endYear
272 mTempDate.clear();
273 if (!TextUtils.isEmpty(maxDate)) {
274 if (!parseDate(maxDate, mTempDate)) {
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800275 mTempDate.set(endYear, 11, 31);
276 }
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800277 } else {
278 mTempDate.set(endYear, 11, 31);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800279 }
Svetoslav Ganov13427a02011-01-31 16:37:05 -0800280 setMaxDate(mTempDate.getTimeInMillis());
281
282 // initialize to current date
283 mCurrentDate.setTimeInMillis(System.currentTimeMillis());
284 init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
285 .get(Calendar.DAY_OF_MONTH), null);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800286
287 // re-order the number spinners to match the current date format
288 reorderSpinners();
Svetoslav Ganov3fec3fe2011-09-01 14:48:37 -0700289
Svetoslav Ganov42138042012-03-20 11:51:39 -0700290 // accessibility
Svetoslav Ganovd11e6152012-03-20 12:13:02 -0700291 setContentDescriptions();
Svetoslav Ganov42138042012-03-20 11:51:39 -0700292
293 // If not explicitly specified this view is important for accessibility.
294 if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
295 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800298
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800299 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800300 * Gets the minimal date supported by this {@link DatePicker} in
301 * milliseconds since January 1, 1970 00:00:00 in
302 * {@link TimeZone#getDefault()} time zone.
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800303 * <p>
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800304 * Note: The default minimal date is 01/01/1900.
305 * <p>
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800306 *
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800307 * @return The minimal supported date.
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800308 */
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800309 public long getMinDate() {
310 return mCalendarView.getMinDate();
311 }
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800312
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800313 /**
314 * Sets the minimal date supported by this {@link NumberPicker} in
315 * milliseconds since January 1, 1970 00:00:00 in
316 * {@link TimeZone#getDefault()} time zone.
317 *
318 * @param minDate The minimal supported date.
319 */
320 public void setMinDate(long minDate) {
321 mTempDate.setTimeInMillis(minDate);
322 if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
323 && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
324 return;
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800325 }
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800326 mMinDate.setTimeInMillis(minDate);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800327 mCalendarView.setMinDate(minDate);
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800328 if (mCurrentDate.before(mMinDate)) {
329 mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
330 updateCalendarView();
331 }
332 updateSpinners();
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800333 }
334
335 /**
336 * Gets the maximal date supported by this {@link DatePicker} in
337 * milliseconds since January 1, 1970 00:00:00 in
338 * {@link TimeZone#getDefault()} time zone.
339 * <p>
340 * Note: The default maximal date is 12/31/2100.
341 * <p>
342 *
343 * @return The maximal supported date.
344 */
345 public long getMaxDate() {
346 return mCalendarView.getMaxDate();
347 }
348
349 /**
350 * Sets the maximal date supported by this {@link DatePicker} in
351 * milliseconds since January 1, 1970 00:00:00 in
352 * {@link TimeZone#getDefault()} time zone.
353 *
354 * @param maxDate The maximal supported date.
355 */
356 public void setMaxDate(long maxDate) {
357 mTempDate.setTimeInMillis(maxDate);
358 if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
359 && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
360 return;
361 }
362 mMaxDate.setTimeInMillis(maxDate);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800363 mCalendarView.setMaxDate(maxDate);
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800364 if (mCurrentDate.after(mMaxDate)) {
365 mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
366 updateCalendarView();
367 }
368 updateSpinners();
Svetoslav Ganov28104e12010-12-19 16:03:07 -0800369 }
370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 @Override
372 public void setEnabled(boolean enabled) {
Svetoslav Ganov51c52ed2010-12-28 13:45:03 -0800373 if (mIsEnabled == enabled) {
374 return;
375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 super.setEnabled(enabled);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800377 mDaySpinner.setEnabled(enabled);
378 mMonthSpinner.setEnabled(enabled);
379 mYearSpinner.setEnabled(enabled);
380 mCalendarView.setEnabled(enabled);
Svetoslav Ganov51c52ed2010-12-28 13:45:03 -0800381 mIsEnabled = enabled;
382 }
383
384 @Override
385 public boolean isEnabled() {
386 return mIsEnabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 }
388
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -0800389 @Override
Svetoslav Ganov3fec3fe2011-09-01 14:48:37 -0700390 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
391 onPopulateAccessibilityEvent(event);
392 return true;
393 }
394
395 @Override
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700396 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
397 super.onPopulateAccessibilityEvent(event);
398
Svetoslav Ganov3fec3fe2011-09-01 14:48:37 -0700399 final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -0800400 String selectedDateUtterance = DateUtils.formatDateTime(mContext,
401 mCurrentDate.getTimeInMillis(), flags);
402 event.getText().add(selectedDateUtterance);
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -0800403 }
404
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700405 @Override
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800406 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
407 super.onInitializeAccessibilityEvent(event);
408 event.setClassName(DatePicker.class.getName());
409 }
410
411 @Override
412 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
413 super.onInitializeAccessibilityNodeInfo(info);
414 info.setClassName(DatePicker.class.getName());
415 }
416
417 @Override
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700418 protected void onConfigurationChanged(Configuration newConfig) {
419 super.onConfigurationChanged(newConfig);
420 setCurrentLocale(newConfig.locale);
421 }
422
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800423 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800424 * Gets whether the {@link CalendarView} is shown.
425 *
426 * @return True if the calendar view is shown.
Svetoslav Ganov5f3f6ce2011-02-24 15:36:13 -0800427 * @see #getCalendarView()
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800428 */
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800429 public boolean getCalendarViewShown() {
Svetoslave10837f2013-03-08 12:43:15 -0800430 return (mCalendarView.getVisibility() == View.VISIBLE);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800431 }
432
433 /**
Svetoslav Ganov5f3f6ce2011-02-24 15:36:13 -0800434 * Gets the {@link CalendarView}.
435 *
436 * @return The calendar view.
437 * @see #getCalendarViewShown()
438 */
439 public CalendarView getCalendarView () {
440 return mCalendarView;
441 }
442
443 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800444 * Sets whether the {@link CalendarView} is shown.
445 *
446 * @param shown True if the calendar view is to be shown.
447 */
448 public void setCalendarViewShown(boolean shown) {
449 mCalendarView.setVisibility(shown ? VISIBLE : GONE);
450 }
451
452 /**
453 * Gets whether the spinners are shown.
454 *
455 * @return True if the spinners are shown.
456 */
457 public boolean getSpinnersShown() {
458 return mSpinners.isShown();
459 }
460
461 /**
462 * Sets whether the spinners are shown.
463 *
464 * @param shown True if the spinners are to be shown.
465 */
466 public void setSpinnersShown(boolean shown) {
467 mSpinners.setVisibility(shown ? VISIBLE : GONE);
468 }
469
470 /**
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700471 * Sets the current locale.
472 *
473 * @param locale The current locale.
474 */
475 private void setCurrentLocale(Locale locale) {
476 if (locale.equals(mCurrentLocale)) {
477 return;
478 }
479
480 mCurrentLocale = locale;
481
482 mTempDate = getCalendarForLocale(mTempDate, locale);
483 mMinDate = getCalendarForLocale(mMinDate, locale);
484 mMaxDate = getCalendarForLocale(mMaxDate, locale);
485 mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
486
487 mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
Elliott Hughes949e9df2013-04-30 13:41:06 -0700488 mShortMonths = new DateFormatSymbols().getShortMonths();
489
490 if (usingNumericMonths()) {
491 // We're in a locale where a date should either be all-numeric, or all-text.
492 // All-text would require custom NumberPicker formatters for day and year.
493 mShortMonths = new String[mNumberOfMonths];
494 for (int i = 0; i < mNumberOfMonths; ++i) {
495 mShortMonths[i] = String.format("%d", i + 1);
496 }
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700497 }
498 }
499
500 /**
Elliott Hughes949e9df2013-04-30 13:41:06 -0700501 * Tests whether the current locale is one where there are no real month names,
502 * such as Chinese, Japanese, or Korean locales.
503 */
504 private boolean usingNumericMonths() {
505 return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
506 }
507
508 /**
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700509 * Gets a calendar for locale bootstrapped with the value of a given calendar.
510 *
511 * @param oldCalendar The old calendar.
512 * @param locale The locale.
513 */
514 private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
515 if (oldCalendar == null) {
516 return Calendar.getInstance(locale);
517 } else {
518 final long currentTimeMillis = oldCalendar.getTimeInMillis();
519 Calendar newCalendar = Calendar.getInstance(locale);
520 newCalendar.setTimeInMillis(currentTimeMillis);
521 return newCalendar;
522 }
523 }
524
525 /**
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700526 * Reorders the spinners according to the date format that is
527 * explicitly set by the user and if no such is set fall back
528 * to the current locale's default format.
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800529 */
530 private void reorderSpinners() {
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700531 mSpinners.removeAllViews();
Elliott Hughes659f1452013-04-30 11:11:53 -0700532 // We use numeric spinners for year and day, but textual months. Ask icu4c what
533 // order the user's locale uses for that combination. http://b/7207103.
534 String pattern = ICU.getBestDateTimePattern("yyyyMMMdd", Locale.getDefault().toString());
535 char[] order = ICU.getDateFormatOrder(pattern);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700536 final int spinnerCount = order.length;
537 for (int i = 0; i < spinnerCount; i++) {
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700538 switch (order[i]) {
Elliott Hughes659f1452013-04-30 11:11:53 -0700539 case 'd':
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700540 mSpinners.addView(mDaySpinner);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700541 setImeOptions(mDaySpinner, spinnerCount, i);
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700542 break;
Elliott Hughes659f1452013-04-30 11:11:53 -0700543 case 'M':
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700544 mSpinners.addView(mMonthSpinner);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700545 setImeOptions(mMonthSpinner, spinnerCount, i);
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700546 break;
Elliott Hughes659f1452013-04-30 11:11:53 -0700547 case 'y':
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700548 mSpinners.addView(mYearSpinner);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700549 setImeOptions(mYearSpinner, spinnerCount, i);
Svetoslav Ganovf583dd32011-03-18 14:41:50 -0700550 break;
551 default:
Elliott Hughes659f1452013-04-30 11:11:53 -0700552 throw new IllegalArgumentException(Arrays.toString(order));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 }
554 }
555 }
556
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800557 /**
558 * Updates the current date.
559 *
560 * @param year The year.
561 * @param month The month which is <strong>starting from zero</strong>.
562 * @param dayOfMonth The day of the month.
563 */
564 public void updateDate(int year, int month, int dayOfMonth) {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800565 if (!isNewDate(year, month, dayOfMonth)) {
566 return;
Kenny Rootdddda8d2010-11-15 14:38:51 -0800567 }
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800568 setDate(year, month, dayOfMonth);
Svetoslav Ganov58f51252011-01-26 22:50:51 -0800569 updateSpinners();
570 updateCalendarView();
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800571 notifyDateChanged();
Kenny Rootdddda8d2010-11-15 14:38:51 -0800572 }
573
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800574 // Override so we are in complete control of save / restore for this widget.
575 @Override
576 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
577 dispatchThawSelfOnly(container);
578 }
579
580 @Override
581 protected Parcelable onSaveInstanceState() {
582 Parcelable superState = super.onSaveInstanceState();
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800583 return new SavedState(superState, getYear(), getMonth(), getDayOfMonth());
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800584 }
585
586 @Override
587 protected void onRestoreInstanceState(Parcelable state) {
588 SavedState ss = (SavedState) state;
589 super.onRestoreInstanceState(ss.getSuperState());
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800590 setDate(ss.mYear, ss.mMonth, ss.mDay);
Svetoslav Ganov58f51252011-01-26 22:50:51 -0800591 updateSpinners();
592 updateCalendarView();
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800593 }
594
595 /**
596 * Initialize the state. If the provided values designate an inconsistent
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800597 * date the values are normalized before updating the spinners.
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800598 *
599 * @param year The initial year.
600 * @param monthOfYear The initial month <strong>starting from zero</strong>.
601 * @param dayOfMonth The initial day of the month.
602 * @param onDateChangedListener How user is notified date is changed by
603 * user, can be null.
604 */
605 public void init(int year, int monthOfYear, int dayOfMonth,
606 OnDateChangedListener onDateChangedListener) {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800607 setDate(year, monthOfYear, dayOfMonth);
Svetoslav Ganov58f51252011-01-26 22:50:51 -0800608 updateSpinners();
609 updateCalendarView();
Svetoslav Ganov2f136a82011-01-13 11:33:05 -0800610 mOnDateChangedListener = onDateChangedListener;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800611 }
612
613 /**
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800614 * Parses the given <code>date</code> and in case of success sets the result
615 * to the <code>outDate</code>.
Svetoslav Ganova911d4a2010-12-08 16:11:30 -0800616 *
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800617 * @return True if the date was parsed.
Svetoslav Ganova911d4a2010-12-08 16:11:30 -0800618 */
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800619 private boolean parseDate(String date, Calendar outDate) {
620 try {
621 outDate.setTime(mDateFormat.parse(date));
622 return true;
623 } catch (ParseException e) {
624 Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
625 return false;
626 }
Svetoslav Ganova911d4a2010-12-08 16:11:30 -0800627 }
628
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800629 private boolean isNewDate(int year, int month, int dayOfMonth) {
630 return (mCurrentDate.get(Calendar.YEAR) != year
631 || mCurrentDate.get(Calendar.MONTH) != dayOfMonth
632 || mCurrentDate.get(Calendar.DAY_OF_MONTH) != month);
633 }
Svetoslav Ganova911d4a2010-12-08 16:11:30 -0800634
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800635 private void setDate(int year, int month, int dayOfMonth) {
636 mCurrentDate.set(year, month, dayOfMonth);
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800637 if (mCurrentDate.before(mMinDate)) {
638 mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
639 } else if (mCurrentDate.after(mMaxDate)) {
640 mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
641 }
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800642 }
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800643
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800644 private void updateSpinners() {
645 // set the spinner ranges respecting the min and max dates
646 if (mCurrentDate.equals(mMinDate)) {
647 mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
648 mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
649 mDaySpinner.setWrapSelectorWheel(false);
650 mMonthSpinner.setDisplayedValues(null);
651 mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
652 mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
653 mMonthSpinner.setWrapSelectorWheel(false);
654 } else if (mCurrentDate.equals(mMaxDate)) {
655 mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
656 mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
657 mDaySpinner.setWrapSelectorWheel(false);
658 mMonthSpinner.setDisplayedValues(null);
659 mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
660 mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
661 mMonthSpinner.setWrapSelectorWheel(false);
662 } else {
663 mDaySpinner.setMinValue(1);
664 mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
665 mDaySpinner.setWrapSelectorWheel(true);
666 mMonthSpinner.setDisplayedValues(null);
667 mMonthSpinner.setMinValue(0);
668 mMonthSpinner.setMaxValue(11);
669 mMonthSpinner.setWrapSelectorWheel(true);
670 }
671
672 // make sure the month names are a zero based array
673 // with the months in the month spinner
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700674 String[] displayedValues = Arrays.copyOfRange(mShortMonths,
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800675 mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
676 mMonthSpinner.setDisplayedValues(displayedValues);
677
678 // year spinner range does not change based on the current date
679 mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
680 mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
681 mYearSpinner.setWrapSelectorWheel(false);
682
683 // set the spinner values
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800684 mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
685 mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800686 mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
Hyejin Kime9a74a12013-03-20 18:14:00 +0900687
Elliott Hughes949e9df2013-04-30 13:41:06 -0700688 if (usingNumericMonths()) {
Hyejin Kime9a74a12013-03-20 18:14:00 +0900689 mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
690 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800691 }
692
693 /**
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800694 * Updates the calendar view with the current date.
Svetoslav Ganove9730bf2010-12-20 21:25:20 -0800695 */
696 private void updateCalendarView() {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800697 mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800698 }
699
700 /**
701 * @return The selected year.
702 */
703 public int getYear() {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800704 return mCurrentDate.get(Calendar.YEAR);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800705 }
706
707 /**
708 * @return The selected month.
709 */
710 public int getMonth() {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800711 return mCurrentDate.get(Calendar.MONTH);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800712 }
713
714 /**
715 * @return The selected day of month.
716 */
717 public int getDayOfMonth() {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800718 return mCurrentDate.get(Calendar.DAY_OF_MONTH);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800719 }
720
721 /**
722 * Notifies the listener, if such, for a change in the selected date.
723 */
724 private void notifyDateChanged() {
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -0800725 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800726 if (mOnDateChangedListener != null) {
Svetoslav Ganov156f2092011-01-24 02:13:36 -0800727 mOnDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth());
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800728 }
729 }
730
731 /**
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700732 * Sets the IME options for a spinner based on its ordering.
733 *
734 * @param spinner The spinner.
735 * @param spinnerCount The total spinner count.
736 * @param spinnerIndex The index of the given spinner.
737 */
738 private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
739 final int imeOptions;
740 if (spinnerIndex < spinnerCount - 1) {
741 imeOptions = EditorInfo.IME_ACTION_NEXT;
742 } else {
743 imeOptions = EditorInfo.IME_ACTION_DONE;
744 }
745 TextView input = (TextView) spinner.findViewById(R.id.numberpicker_input);
746 input.setImeOptions(imeOptions);
747 }
748
749 private void setContentDescriptions() {
750 // Day
Svetoslav Ganovd11e6152012-03-20 12:13:02 -0700751 trySetContentDescription(mDaySpinner, R.id.increment,
752 R.string.date_picker_increment_day_button);
753 trySetContentDescription(mDaySpinner, R.id.decrement,
754 R.string.date_picker_decrement_day_button);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700755 // Month
Svetoslav Ganovd11e6152012-03-20 12:13:02 -0700756 trySetContentDescription(mMonthSpinner, R.id.increment,
757 R.string.date_picker_increment_month_button);
758 trySetContentDescription(mMonthSpinner, R.id.decrement,
759 R.string.date_picker_decrement_month_button);
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700760 // Year
Svetoslav Ganovd11e6152012-03-20 12:13:02 -0700761 trySetContentDescription(mYearSpinner, R.id.increment,
762 R.string.date_picker_increment_year_button);
763 trySetContentDescription(mYearSpinner, R.id.decrement,
764 R.string.date_picker_decrement_year_button);
765 }
766
767 private void trySetContentDescription(View root, int viewId, int contDescResId) {
768 View target = root.findViewById(viewId);
769 if (target != null) {
770 target.setContentDescription(mContext.getString(contDescResId));
771 }
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700772 }
773
Svetoslav Ganov6304b0d2011-10-19 19:55:44 -0700774 private void updateInputState() {
775 // Make sure that if the user changes the value and the IME is active
776 // for one of the inputs if this widget, the IME is closed. If the user
777 // changed the value via the IME and there is a next input the IME will
778 // be shown, otherwise the user chose another means of changing the
779 // value and having the IME up makes no sense.
780 InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
781 if (inputMethodManager != null) {
782 if (inputMethodManager.isActive(mYearSpinnerInput)) {
783 mYearSpinnerInput.clearFocus();
784 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
785 } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
786 mMonthSpinnerInput.clearFocus();
787 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
788 } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
789 mDaySpinnerInput.clearFocus();
790 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
791 }
792 }
793 }
794
Svetoslav Ganova53efe92011-09-08 18:08:36 -0700795 /**
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800796 * Class for managing state storing/restoring.
797 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 private static class SavedState extends BaseSavedState {
799
800 private final int mYear;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 private final int mMonth;
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 private final int mDay;
805
806 /**
807 * Constructor called from {@link DatePicker#onSaveInstanceState()}
808 */
809 private SavedState(Parcelable superState, int year, int month, int day) {
810 super(superState);
811 mYear = year;
812 mMonth = month;
813 mDay = day;
814 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 /**
817 * Constructor called from {@link #CREATOR}
818 */
819 private SavedState(Parcel in) {
820 super(in);
821 mYear = in.readInt();
822 mMonth = in.readInt();
823 mDay = in.readInt();
824 }
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 @Override
827 public void writeToParcel(Parcel dest, int flags) {
828 super.writeToParcel(dest, flags);
829 dest.writeInt(mYear);
830 dest.writeInt(mMonth);
831 dest.writeInt(mDay);
832 }
833
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800834 @SuppressWarnings("all")
835 // suppress unused and hiding
836 public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800838 public SavedState createFromParcel(Parcel in) {
839 return new SavedState(in);
840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800842 public SavedState[] newArray(int size) {
843 return new SavedState[size];
844 }
845 };
Kenneth Anderssone3491b62010-03-05 09:16:24 +0100846 }
Svetoslav Ganov3fec3fe2011-09-01 14:48:37 -0700847}