| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.widget; |
| |
| import com.android.internal.R; |
| |
| import android.annotation.Widget; |
| import android.content.Context; |
| import android.content.res.TypedArray; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.text.TextUtils; |
| import android.text.format.DateFormat; |
| import android.text.format.DateUtils; |
| import android.util.AttributeSet; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.view.LayoutInflater; |
| import android.view.accessibility.AccessibilityEvent; |
| import android.widget.NumberPicker.OnValueChangeListener; |
| |
| import java.text.ParseException; |
| import java.text.SimpleDateFormat; |
| import java.util.Arrays; |
| import java.util.Calendar; |
| import java.util.Locale; |
| import java.util.TimeZone; |
| |
| /** |
| * This class is a widget for selecting a date. The date can be selected by a |
| * year, month, and day spinners or a {@link CalendarView}. The set of spinners |
| * and the calendar view are automatically synchronized. The client can |
| * customize whether only the spinners, or only the calendar view, or both to be |
| * displayed. Also the minimal and maximal date from which dates to be selected |
| * can be customized. |
| * <p> |
| * See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date |
| * Picker tutorial</a>. |
| * </p> |
| * <p> |
| * For a dialog using this view, see {@link android.app.DatePickerDialog}. |
| * </p> |
| * |
| * @attr ref android.R.styleable#DatePicker_startYear |
| * @attr ref android.R.styleable#DatePicker_endYear |
| * @attr ref android.R.styleable#DatePicker_maxDate |
| * @attr ref android.R.styleable#DatePicker_minDate |
| * @attr ref android.R.styleable#DatePicker_spinnersShown |
| * @attr ref android.R.styleable#DatePicker_calendarViewShown |
| */ |
| @Widget |
| public class DatePicker extends FrameLayout { |
| |
| private static final String LOG_TAG = DatePicker.class.getSimpleName(); |
| |
| private static final String DATE_FORMAT = "MM/dd/yyyy"; |
| |
| private static final int DEFAULT_START_YEAR = 1900; |
| |
| private static final int DEFAULT_END_YEAR = 2100; |
| |
| private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true; |
| |
| private static final boolean DEFAULT_SPINNERS_SHOWN = true; |
| |
| private static final boolean DEFAULT_ENABLED_STATE = true; |
| |
| private final NumberPicker mDaySpinner; |
| |
| private final LinearLayout mSpinners; |
| |
| private final NumberPicker mMonthSpinner; |
| |
| private final NumberPicker mYearSpinner; |
| |
| private final CalendarView mCalendarView; |
| |
| private OnDateChangedListener mOnDateChangedListener; |
| |
| private Locale mMonthLocale; |
| |
| private final Calendar mTempDate = Calendar.getInstance(); |
| |
| private final int mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1; |
| |
| private final String[] mShortMonths = new String[mNumberOfMonths]; |
| |
| private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT); |
| |
| private final Calendar mMinDate = Calendar.getInstance(); |
| |
| private final Calendar mMaxDate = Calendar.getInstance(); |
| |
| private final Calendar mCurrentDate = Calendar.getInstance(); |
| |
| private boolean mIsEnabled = DEFAULT_ENABLED_STATE; |
| |
| /** |
| * The callback used to indicate the user changes\d the date. |
| */ |
| public interface OnDateChangedListener { |
| |
| /** |
| * Called upon a date change. |
| * |
| * @param view The view associated with this listener. |
| * @param year The year that was set. |
| * @param monthOfYear The month that was set (0-11) for compatibility |
| * with {@link java.util.Calendar}. |
| * @param dayOfMonth The day of the month that was set. |
| */ |
| void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); |
| } |
| |
| public DatePicker(Context context) { |
| this(context, null); |
| } |
| |
| public DatePicker(Context context, AttributeSet attrs) { |
| this(context, attrs, R.attr.datePickerStyle); |
| } |
| |
| public DatePicker(Context context, AttributeSet attrs, int defStyle) { |
| super(context, attrs, defStyle); |
| |
| TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, |
| defStyle, 0); |
| boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown, |
| DEFAULT_SPINNERS_SHOWN); |
| boolean calendarViewShown = attributesArray.getBoolean( |
| R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN); |
| int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear, |
| DEFAULT_START_YEAR); |
| int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR); |
| String minDate = attributesArray.getString(R.styleable.DatePicker_minDate); |
| String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate); |
| int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_layout, |
| R.layout.date_picker); |
| attributesArray.recycle(); |
| |
| LayoutInflater inflater = (LayoutInflater) context |
| .getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| inflater.inflate(layoutResourceId, this, true); |
| |
| OnValueChangeListener onChangeListener = new OnValueChangeListener() { |
| public void onValueChange(NumberPicker picker, int oldVal, int newVal) { |
| mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis()); |
| // take care of wrapping of days and months to update greater fields |
| if (picker == mDaySpinner) { |
| int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH); |
| if (oldVal == maxDayOfMonth && newVal == 1) { |
| mTempDate.add(Calendar.DAY_OF_MONTH, 1); |
| } else if (oldVal == 1 && newVal == maxDayOfMonth) { |
| mTempDate.add(Calendar.DAY_OF_MONTH, -1); |
| } else { |
| mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal); |
| } |
| } else if (picker == mMonthSpinner) { |
| if (oldVal == 11 && newVal == 0) { |
| mTempDate.add(Calendar.MONTH, 1); |
| } else if (oldVal == 0 && newVal == 11) { |
| mTempDate.add(Calendar.MONTH, -1); |
| } else { |
| mTempDate.add(Calendar.MONTH, newVal - oldVal); |
| } |
| } else if (picker == mYearSpinner) { |
| mTempDate.set(Calendar.YEAR, newVal); |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| // now set the date to the adjusted one |
| setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH), |
| mTempDate.get(Calendar.DAY_OF_MONTH)); |
| updateSpinners(); |
| updateCalendarView(); |
| notifyDateChanged(); |
| } |
| }; |
| |
| mSpinners = (LinearLayout) findViewById(R.id.pickers); |
| |
| // calendar view day-picker |
| mCalendarView = (CalendarView) findViewById(R.id.calendar_view); |
| mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { |
| public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) { |
| setDate(year, month, monthDay); |
| updateSpinners(); |
| notifyDateChanged(); |
| } |
| }); |
| |
| // day |
| mDaySpinner = (NumberPicker) findViewById(R.id.day); |
| mDaySpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER); |
| mDaySpinner.setOnLongPressUpdateInterval(100); |
| mDaySpinner.setOnValueChangedListener(onChangeListener); |
| |
| // month |
| mMonthSpinner = (NumberPicker) findViewById(R.id.month); |
| mMonthSpinner.setMinValue(0); |
| mMonthSpinner.setMaxValue(mNumberOfMonths - 1); |
| mMonthSpinner.setDisplayedValues(getShortMonths()); |
| mMonthSpinner.setOnLongPressUpdateInterval(200); |
| mMonthSpinner.setOnValueChangedListener(onChangeListener); |
| |
| // year |
| mYearSpinner = (NumberPicker) findViewById(R.id.year); |
| mYearSpinner.setOnLongPressUpdateInterval(100); |
| mYearSpinner.setOnValueChangedListener(onChangeListener); |
| |
| // show only what the user required but make sure we |
| // show something and the spinners have higher priority |
| if (!spinnersShown && !calendarViewShown) { |
| setSpinnersShown(true); |
| } else { |
| setSpinnersShown(spinnersShown); |
| setCalendarViewShown(calendarViewShown); |
| |
| // set the min date giving priority of the minDate over startYear |
| mTempDate.clear(); |
| if (!TextUtils.isEmpty(minDate)) { |
| if (!parseDate(minDate, mTempDate)) { |
| mTempDate.set(startYear, 0, 1); |
| } |
| } else { |
| mTempDate.set(startYear, 0, 1); |
| } |
| mMinDate.clear(); |
| setMinDate(mTempDate.getTimeInMillis()); |
| |
| // set the max date giving priority of the minDate over startYear |
| mTempDate.clear(); |
| if (!TextUtils.isEmpty(maxDate)) { |
| if (!parseDate(maxDate, mTempDate)) { |
| mTempDate.set(endYear, 11, 31); |
| } |
| } else { |
| mTempDate.set(endYear, 11, 31); |
| } |
| mMaxDate.clear(); |
| setMaxDate(mTempDate.getTimeInMillis()); |
| |
| // initialize to current date |
| mCurrentDate.setTimeInMillis(System.currentTimeMillis()); |
| init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate |
| .get(Calendar.DAY_OF_MONTH), null); |
| } |
| |
| // re-order the number spinners to match the current date format |
| reorderSpinners(); |
| } |
| |
| /** |
| * Gets the minimal date supported by this {@link DatePicker} in |
| * milliseconds since January 1, 1970 00:00:00 in |
| * {@link TimeZone#getDefault()} time zone. |
| * <p> |
| * Note: The default minimal date is 01/01/1900. |
| * <p> |
| * |
| * @return The minimal supported date. |
| */ |
| public long getMinDate() { |
| return mCalendarView.getMinDate(); |
| } |
| |
| /** |
| * Sets the minimal date supported by this {@link NumberPicker} in |
| * milliseconds since January 1, 1970 00:00:00 in |
| * {@link TimeZone#getDefault()} time zone. |
| * |
| * @param minDate The minimal supported date. |
| */ |
| public void setMinDate(long minDate) { |
| mTempDate.setTimeInMillis(minDate); |
| if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) |
| && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) { |
| return; |
| } |
| mMinDate.setTimeInMillis(minDate); |
| mCalendarView.setMinDate(minDate); |
| if (mCurrentDate.before(mMinDate)) { |
| mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); |
| updateCalendarView(); |
| } |
| updateSpinners(); |
| } |
| |
| /** |
| * Gets the maximal date supported by this {@link DatePicker} in |
| * milliseconds since January 1, 1970 00:00:00 in |
| * {@link TimeZone#getDefault()} time zone. |
| * <p> |
| * Note: The default maximal date is 12/31/2100. |
| * <p> |
| * |
| * @return The maximal supported date. |
| */ |
| public long getMaxDate() { |
| return mCalendarView.getMaxDate(); |
| } |
| |
| /** |
| * Sets the maximal date supported by this {@link DatePicker} in |
| * milliseconds since January 1, 1970 00:00:00 in |
| * {@link TimeZone#getDefault()} time zone. |
| * |
| * @param maxDate The maximal supported date. |
| */ |
| public void setMaxDate(long maxDate) { |
| mTempDate.setTimeInMillis(maxDate); |
| if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR) |
| && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) { |
| return; |
| } |
| mMaxDate.setTimeInMillis(maxDate); |
| mCalendarView.setMaxDate(maxDate); |
| if (mCurrentDate.after(mMaxDate)) { |
| mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); |
| updateCalendarView(); |
| } |
| updateSpinners(); |
| } |
| |
| @Override |
| public void setEnabled(boolean enabled) { |
| if (mIsEnabled == enabled) { |
| return; |
| } |
| super.setEnabled(enabled); |
| mDaySpinner.setEnabled(enabled); |
| mMonthSpinner.setEnabled(enabled); |
| mYearSpinner.setEnabled(enabled); |
| mCalendarView.setEnabled(enabled); |
| mIsEnabled = enabled; |
| } |
| |
| @Override |
| public boolean isEnabled() { |
| return mIsEnabled; |
| } |
| |
| @Override |
| public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { |
| int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
| | DateUtils.FORMAT_SHOW_YEAR; |
| String selectedDateUtterance = DateUtils.formatDateTime(mContext, |
| mCurrentDate.getTimeInMillis(), flags); |
| event.getText().add(selectedDateUtterance); |
| return true; |
| } |
| |
| /** |
| * Gets whether the {@link CalendarView} is shown. |
| * |
| * @return True if the calendar view is shown. |
| */ |
| public boolean getCalendarViewShown() { |
| return mCalendarView.isShown(); |
| } |
| |
| /** |
| * Sets whether the {@link CalendarView} is shown. |
| * |
| * @param shown True if the calendar view is to be shown. |
| */ |
| public void setCalendarViewShown(boolean shown) { |
| mCalendarView.setVisibility(shown ? VISIBLE : GONE); |
| } |
| |
| /** |
| * Gets whether the spinners are shown. |
| * |
| * @return True if the spinners are shown. |
| */ |
| public boolean getSpinnersShown() { |
| return mSpinners.isShown(); |
| } |
| |
| /** |
| * Sets whether the spinners are shown. |
| * |
| * @param shown True if the spinners are to be shown. |
| */ |
| public void setSpinnersShown(boolean shown) { |
| mSpinners.setVisibility(shown ? VISIBLE : GONE); |
| } |
| |
| /** |
| * Reorders the spinners according to the date format in the current |
| * {@link Locale}. |
| */ |
| private void reorderSpinners() { |
| java.text.DateFormat format; |
| String order; |
| |
| /* |
| * If the user is in a locale where the medium date format is still |
| * numeric (Japanese and Czech, for example), respect the date format |
| * order setting. Otherwise, use the order that the locale says is |
| * appropriate for a spelled-out date. |
| */ |
| |
| if (getShortMonths()[0].startsWith("1")) { |
| format = DateFormat.getDateFormat(getContext()); |
| } else { |
| format = DateFormat.getMediumDateFormat(getContext()); |
| } |
| |
| if (format instanceof SimpleDateFormat) { |
| order = ((SimpleDateFormat) format).toPattern(); |
| } else { |
| // Shouldn't happen, but just in case. |
| order = new String(DateFormat.getDateFormatOrder(getContext())); |
| } |
| |
| /* |
| * Remove the 3 spinners from their parent and then add them back in the |
| * required order. |
| */ |
| LinearLayout parent = mSpinners; |
| parent.removeAllViews(); |
| |
| boolean quoted = false; |
| boolean didDay = false, didMonth = false, didYear = false; |
| |
| for (int i = 0; i < order.length(); i++) { |
| char c = order.charAt(i); |
| |
| if (c == '\'') { |
| quoted = !quoted; |
| } |
| |
| if (!quoted) { |
| if (c == DateFormat.DATE && !didDay) { |
| parent.addView(mDaySpinner); |
| didDay = true; |
| } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) { |
| parent.addView(mMonthSpinner); |
| didMonth = true; |
| } else if (c == DateFormat.YEAR && !didYear) { |
| parent.addView(mYearSpinner); |
| didYear = true; |
| } |
| } |
| } |
| |
| // Shouldn't happen, but just in case. |
| if (!didMonth) { |
| parent.addView(mMonthSpinner); |
| } |
| if (!didDay) { |
| parent.addView(mDaySpinner); |
| } |
| if (!didYear) { |
| parent.addView(mYearSpinner); |
| } |
| } |
| |
| /** |
| * Updates the current date. |
| * |
| * @param year The year. |
| * @param month The month which is <strong>starting from zero</strong>. |
| * @param dayOfMonth The day of the month. |
| */ |
| public void updateDate(int year, int month, int dayOfMonth) { |
| if (!isNewDate(year, month, dayOfMonth)) { |
| return; |
| } |
| setDate(year, month, dayOfMonth); |
| updateSpinners(); |
| updateCalendarView(); |
| notifyDateChanged(); |
| } |
| |
| // Override so we are in complete control of save / restore for this widget. |
| @Override |
| protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { |
| dispatchThawSelfOnly(container); |
| } |
| |
| @Override |
| protected Parcelable onSaveInstanceState() { |
| Parcelable superState = super.onSaveInstanceState(); |
| return new SavedState(superState, getYear(), getMonth(), getDayOfMonth()); |
| } |
| |
| @Override |
| protected void onRestoreInstanceState(Parcelable state) { |
| SavedState ss = (SavedState) state; |
| super.onRestoreInstanceState(ss.getSuperState()); |
| setDate(ss.mYear, ss.mMonth, ss.mDay); |
| updateSpinners(); |
| updateCalendarView(); |
| } |
| |
| /** |
| * Initialize the state. If the provided values designate an inconsistent |
| * date the values are normalized before updating the spinners. |
| * |
| * @param year The initial year. |
| * @param monthOfYear The initial month <strong>starting from zero</strong>. |
| * @param dayOfMonth The initial day of the month. |
| * @param onDateChangedListener How user is notified date is changed by |
| * user, can be null. |
| */ |
| public void init(int year, int monthOfYear, int dayOfMonth, |
| OnDateChangedListener onDateChangedListener) { |
| setDate(year, monthOfYear, dayOfMonth); |
| updateSpinners(); |
| updateCalendarView(); |
| mOnDateChangedListener = onDateChangedListener; |
| } |
| |
| /** |
| * Parses the given <code>date</code> and in case of success sets the result |
| * to the <code>outDate</code>. |
| * |
| * @return True if the date was parsed. |
| */ |
| private boolean parseDate(String date, Calendar outDate) { |
| try { |
| outDate.setTime(mDateFormat.parse(date)); |
| return true; |
| } catch (ParseException e) { |
| Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT); |
| return false; |
| } |
| } |
| |
| /** |
| * @return The short month abbreviations. |
| */ |
| private String[] getShortMonths() { |
| final Locale currentLocale = Locale.getDefault(); |
| if (currentLocale.equals(mMonthLocale)) { |
| return mShortMonths; |
| } else { |
| for (int i = 0; i < mNumberOfMonths; i++) { |
| mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i, |
| DateUtils.LENGTH_MEDIUM); |
| } |
| mMonthLocale = currentLocale; |
| return mShortMonths; |
| } |
| } |
| |
| private boolean isNewDate(int year, int month, int dayOfMonth) { |
| return (mCurrentDate.get(Calendar.YEAR) != year |
| || mCurrentDate.get(Calendar.MONTH) != dayOfMonth |
| || mCurrentDate.get(Calendar.DAY_OF_MONTH) != month); |
| } |
| |
| private void setDate(int year, int month, int dayOfMonth) { |
| mCurrentDate.set(year, month, dayOfMonth); |
| if (mCurrentDate.before(mMinDate)) { |
| mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); |
| } else if (mCurrentDate.after(mMaxDate)) { |
| mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); |
| } |
| } |
| |
| private void updateSpinners() { |
| // set the spinner ranges respecting the min and max dates |
| if (mCurrentDate.equals(mMinDate)) { |
| mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); |
| mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); |
| mDaySpinner.setWrapSelectorWheel(false); |
| mMonthSpinner.setDisplayedValues(null); |
| mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH)); |
| mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH)); |
| mMonthSpinner.setWrapSelectorWheel(false); |
| } else if (mCurrentDate.equals(mMaxDate)) { |
| mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH)); |
| mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); |
| mDaySpinner.setWrapSelectorWheel(false); |
| mMonthSpinner.setDisplayedValues(null); |
| mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH)); |
| mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH)); |
| mMonthSpinner.setWrapSelectorWheel(false); |
| } else { |
| mDaySpinner.setMinValue(1); |
| mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); |
| mDaySpinner.setWrapSelectorWheel(true); |
| mMonthSpinner.setDisplayedValues(null); |
| mMonthSpinner.setMinValue(0); |
| mMonthSpinner.setMaxValue(11); |
| mMonthSpinner.setWrapSelectorWheel(true); |
| } |
| |
| // make sure the month names are a zero based array |
| // with the months in the month spinner |
| String[] displayedValues = Arrays.copyOfRange(getShortMonths(), |
| mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1); |
| mMonthSpinner.setDisplayedValues(displayedValues); |
| |
| // year spinner range does not change based on the current date |
| mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR)); |
| mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR)); |
| mYearSpinner.setWrapSelectorWheel(false); |
| |
| // set the spinner values |
| mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR)); |
| mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH)); |
| mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); |
| } |
| |
| /** |
| * Updates the calendar view with the current date. |
| */ |
| private void updateCalendarView() { |
| mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false); |
| } |
| |
| /** |
| * @return The selected year. |
| */ |
| public int getYear() { |
| return mCurrentDate.get(Calendar.YEAR); |
| } |
| |
| /** |
| * @return The selected month. |
| */ |
| public int getMonth() { |
| return mCurrentDate.get(Calendar.MONTH); |
| } |
| |
| /** |
| * @return The selected day of month. |
| */ |
| public int getDayOfMonth() { |
| return mCurrentDate.get(Calendar.DAY_OF_MONTH); |
| } |
| |
| /** |
| * Notifies the listener, if such, for a change in the selected date. |
| */ |
| private void notifyDateChanged() { |
| sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); |
| if (mOnDateChangedListener != null) { |
| mOnDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth()); |
| } |
| } |
| |
| /** |
| * Class for managing state storing/restoring. |
| */ |
| private static class SavedState extends BaseSavedState { |
| |
| private final int mYear; |
| |
| private final int mMonth; |
| |
| private final int mDay; |
| |
| /** |
| * Constructor called from {@link DatePicker#onSaveInstanceState()} |
| */ |
| private SavedState(Parcelable superState, int year, int month, int day) { |
| super(superState); |
| mYear = year; |
| mMonth = month; |
| mDay = day; |
| } |
| |
| /** |
| * Constructor called from {@link #CREATOR} |
| */ |
| private SavedState(Parcel in) { |
| super(in); |
| mYear = in.readInt(); |
| mMonth = in.readInt(); |
| mDay = in.readInt(); |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| super.writeToParcel(dest, flags); |
| dest.writeInt(mYear); |
| dest.writeInt(mMonth); |
| dest.writeInt(mDay); |
| } |
| |
| @SuppressWarnings("all") |
| // suppress unused and hiding |
| public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { |
| |
| public SavedState createFromParcel(Parcel in) { |
| return new SavedState(in); |
| } |
| |
| public SavedState[] newArray(int size) { |
| return new SavedState[size]; |
| } |
| }; |
| } |
| } |