Home | History | Annotate | Download | only in widget
      1 /*
      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 
     17 package android.widget;
     18 
     19 import com.android.internal.R;
     20 
     21 import android.annotation.IntDef;
     22 import android.annotation.Nullable;
     23 import android.annotation.TestApi;
     24 import android.annotation.Widget;
     25 import android.content.Context;
     26 import android.content.res.Configuration;
     27 import android.content.res.TypedArray;
     28 import android.icu.util.Calendar;
     29 import android.icu.util.TimeZone;
     30 import android.os.Parcel;
     31 import android.os.Parcelable;
     32 import android.util.AttributeSet;
     33 import android.util.SparseArray;
     34 import android.view.View;
     35 import android.view.accessibility.AccessibilityEvent;
     36 
     37 import java.lang.annotation.Retention;
     38 import java.lang.annotation.RetentionPolicy;
     39 import java.util.Locale;
     40 
     41 /**
     42  * Provides a widget for selecting a date.
     43  * <p>
     44  * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is
     45  * set to {@code spinner}, the date can be selected using year, month, and day
     46  * spinners or a {@link CalendarView}. The set of spinners and the calendar
     47  * view are automatically synchronized. The client can customize whether only
     48  * the spinners, or only the calendar view, or both to be displayed.
     49  * </p>
     50  * <p>
     51  * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is
     52  * set to {@code calendar}, the month and day can be selected using a
     53  * calendar-style view while the year can be selected separately using a list.
     54  * </p>
     55  * <p>
     56  * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
     57  * guide.
     58  * </p>
     59  * <p>
     60  * For a dialog using this view, see {@link android.app.DatePickerDialog}.
     61  * </p>
     62  *
     63  * @attr ref android.R.styleable#DatePicker_startYear
     64  * @attr ref android.R.styleable#DatePicker_endYear
     65  * @attr ref android.R.styleable#DatePicker_maxDate
     66  * @attr ref android.R.styleable#DatePicker_minDate
     67  * @attr ref android.R.styleable#DatePicker_spinnersShown
     68  * @attr ref android.R.styleable#DatePicker_calendarViewShown
     69  * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground
     70  * @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance
     71  * @attr ref android.R.styleable#DatePicker_headerBackground
     72  * @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance
     73  * @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance
     74  * @attr ref android.R.styleable#DatePicker_headerYearTextAppearance
     75  * @attr ref android.R.styleable#DatePicker_yearListItemTextAppearance
     76  * @attr ref android.R.styleable#DatePicker_yearListSelectorColor
     77  * @attr ref android.R.styleable#DatePicker_calendarTextColor
     78  * @attr ref android.R.styleable#DatePicker_datePickerMode
     79  */
     80 @Widget
     81 public class DatePicker extends FrameLayout {
     82     /**
     83      * Presentation mode for the Holo-style date picker that uses a set of
     84      * {@link android.widget.NumberPicker}s.
     85      *
     86      * @see #getMode()
     87      * @hide Visible for testing only.
     88      */
     89     @TestApi
     90     public static final int MODE_SPINNER = 1;
     91 
     92     /**
     93      * Presentation mode for the Material-style date picker that uses a
     94      * calendar.
     95      *
     96      * @see #getMode()
     97      * @hide Visible for testing only.
     98      */
     99     @TestApi
    100     public static final int MODE_CALENDAR = 2;
    101 
    102     /** @hide */
    103     @IntDef({MODE_SPINNER, MODE_CALENDAR})
    104     @Retention(RetentionPolicy.SOURCE)
    105     public @interface DatePickerMode {}
    106 
    107     private final DatePickerDelegate mDelegate;
    108 
    109     @DatePickerMode
    110     private final int mMode;
    111 
    112     /**
    113      * The callback used to indicate the user changed the date.
    114      */
    115     public interface OnDateChangedListener {
    116 
    117         /**
    118          * Called upon a date change.
    119          *
    120          * @param view The view associated with this listener.
    121          * @param year The year that was set.
    122          * @param monthOfYear The month that was set (0-11) for compatibility
    123          *            with {@link java.util.Calendar}.
    124          * @param dayOfMonth The day of the month that was set.
    125          */
    126         void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
    127     }
    128 
    129     public DatePicker(Context context) {
    130         this(context, null);
    131     }
    132 
    133     public DatePicker(Context context, AttributeSet attrs) {
    134         this(context, attrs, R.attr.datePickerStyle);
    135     }
    136 
    137     public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) {
    138         this(context, attrs, defStyleAttr, 0);
    139     }
    140 
    141     public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    142         super(context, attrs, defStyleAttr, defStyleRes);
    143 
    144         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
    145                 defStyleAttr, defStyleRes);
    146         final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
    147         final int requestedMode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
    148         final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
    149         a.recycle();
    150 
    151         if (requestedMode == MODE_CALENDAR && isDialogMode) {
    152             // You want MODE_CALENDAR? YOU CAN'T HANDLE MODE_CALENDAR! Well,
    153             // maybe you can depending on your screen size. Let's check...
    154             mMode = context.getResources().getInteger(R.integer.date_picker_mode);
    155         } else {
    156             mMode = requestedMode;
    157         }
    158 
    159         switch (mMode) {
    160             case MODE_CALENDAR:
    161                 mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes);
    162                 break;
    163             case MODE_SPINNER:
    164             default:
    165                 mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes);
    166                 break;
    167         }
    168 
    169         if (firstDayOfWeek != 0) {
    170             setFirstDayOfWeek(firstDayOfWeek);
    171         }
    172     }
    173 
    174     private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs,
    175             int defStyleAttr, int defStyleRes) {
    176         return new DatePickerSpinnerDelegate(this, context, attrs, defStyleAttr, defStyleRes);
    177     }
    178 
    179     private DatePickerDelegate createCalendarUIDelegate(Context context, AttributeSet attrs,
    180             int defStyleAttr, int defStyleRes) {
    181         return new DatePickerCalendarDelegate(this, context, attrs, defStyleAttr,
    182                 defStyleRes);
    183     }
    184 
    185     /**
    186      * @return the picker's presentation mode, one of {@link #MODE_CALENDAR} or
    187      *         {@link #MODE_SPINNER}
    188      * @attr ref android.R.styleable#DatePicker_datePickerMode
    189      * @hide Visible for testing only.
    190      */
    191     @DatePickerMode
    192     @TestApi
    193     public int getMode() {
    194         return mMode;
    195     }
    196 
    197     /**
    198      * Initialize the state. If the provided values designate an inconsistent
    199      * date the values are normalized before updating the spinners.
    200      *
    201      * @param year The initial year.
    202      * @param monthOfYear The initial month <strong>starting from zero</strong>.
    203      * @param dayOfMonth The initial day of the month.
    204      * @param onDateChangedListener How user is notified date is changed by
    205      *            user, can be null.
    206      */
    207     public void init(int year, int monthOfYear, int dayOfMonth,
    208                      OnDateChangedListener onDateChangedListener) {
    209         mDelegate.init(year, monthOfYear, dayOfMonth, onDateChangedListener);
    210     }
    211 
    212     /**
    213      * Update the current date.
    214      *
    215      * @param year The year.
    216      * @param month The month which is <strong>starting from zero</strong>.
    217      * @param dayOfMonth The day of the month.
    218      */
    219     public void updateDate(int year, int month, int dayOfMonth) {
    220         mDelegate.updateDate(year, month, dayOfMonth);
    221     }
    222 
    223     /**
    224      * @return The selected year.
    225      */
    226     public int getYear() {
    227         return mDelegate.getYear();
    228     }
    229 
    230     /**
    231      * @return The selected month.
    232      */
    233     public int getMonth() {
    234         return mDelegate.getMonth();
    235     }
    236 
    237     /**
    238      * @return The selected day of month.
    239      */
    240     public int getDayOfMonth() {
    241         return mDelegate.getDayOfMonth();
    242     }
    243 
    244     /**
    245      * Gets the minimal date supported by this {@link DatePicker} in
    246      * milliseconds since January 1, 1970 00:00:00 in
    247      * {@link TimeZone#getDefault()} time zone.
    248      * <p>
    249      * Note: The default minimal date is 01/01/1900.
    250      * <p>
    251      *
    252      * @return The minimal supported date.
    253      */
    254     public long getMinDate() {
    255         return mDelegate.getMinDate().getTimeInMillis();
    256     }
    257 
    258     /**
    259      * Sets the minimal date supported by this {@link NumberPicker} in
    260      * milliseconds since January 1, 1970 00:00:00 in
    261      * {@link TimeZone#getDefault()} time zone.
    262      *
    263      * @param minDate The minimal supported date.
    264      */
    265     public void setMinDate(long minDate) {
    266         mDelegate.setMinDate(minDate);
    267     }
    268 
    269     /**
    270      * Gets the maximal date supported by this {@link DatePicker} in
    271      * milliseconds since January 1, 1970 00:00:00 in
    272      * {@link TimeZone#getDefault()} time zone.
    273      * <p>
    274      * Note: The default maximal date is 12/31/2100.
    275      * <p>
    276      *
    277      * @return The maximal supported date.
    278      */
    279     public long getMaxDate() {
    280         return mDelegate.getMaxDate().getTimeInMillis();
    281     }
    282 
    283     /**
    284      * Sets the maximal date supported by this {@link DatePicker} in
    285      * milliseconds since January 1, 1970 00:00:00 in
    286      * {@link TimeZone#getDefault()} time zone.
    287      *
    288      * @param maxDate The maximal supported date.
    289      */
    290     public void setMaxDate(long maxDate) {
    291         mDelegate.setMaxDate(maxDate);
    292     }
    293 
    294     /**
    295      * Sets the callback that indicates the current date is valid.
    296      *
    297      * @param callback the callback, may be null
    298      * @hide
    299      */
    300     public void setValidationCallback(@Nullable ValidationCallback callback) {
    301         mDelegate.setValidationCallback(callback);
    302     }
    303 
    304     @Override
    305     public void setEnabled(boolean enabled) {
    306         if (mDelegate.isEnabled() == enabled) {
    307             return;
    308         }
    309         super.setEnabled(enabled);
    310         mDelegate.setEnabled(enabled);
    311     }
    312 
    313     @Override
    314     public boolean isEnabled() {
    315         return mDelegate.isEnabled();
    316     }
    317 
    318     /** @hide */
    319     @Override
    320     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
    321         return mDelegate.dispatchPopulateAccessibilityEvent(event);
    322     }
    323 
    324     /** @hide */
    325     @Override
    326     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
    327         super.onPopulateAccessibilityEventInternal(event);
    328         mDelegate.onPopulateAccessibilityEvent(event);
    329     }
    330 
    331     @Override
    332     public CharSequence getAccessibilityClassName() {
    333         return DatePicker.class.getName();
    334     }
    335 
    336     @Override
    337     protected void onConfigurationChanged(Configuration newConfig) {
    338         super.onConfigurationChanged(newConfig);
    339         mDelegate.onConfigurationChanged(newConfig);
    340     }
    341 
    342     /**
    343      * Sets the first day of week.
    344      *
    345      * @param firstDayOfWeek The first day of the week conforming to the
    346      *            {@link CalendarView} APIs.
    347      * @see Calendar#SUNDAY
    348      * @see Calendar#MONDAY
    349      * @see Calendar#TUESDAY
    350      * @see Calendar#WEDNESDAY
    351      * @see Calendar#THURSDAY
    352      * @see Calendar#FRIDAY
    353      * @see Calendar#SATURDAY
    354      *
    355      * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
    356      */
    357     public void setFirstDayOfWeek(int firstDayOfWeek) {
    358         if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) {
    359             throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7");
    360         }
    361         mDelegate.setFirstDayOfWeek(firstDayOfWeek);
    362     }
    363 
    364     /**
    365      * Gets the first day of week.
    366      *
    367      * @return The first day of the week conforming to the {@link CalendarView}
    368      *         APIs.
    369      * @see Calendar#SUNDAY
    370      * @see Calendar#MONDAY
    371      * @see Calendar#TUESDAY
    372      * @see Calendar#WEDNESDAY
    373      * @see Calendar#THURSDAY
    374      * @see Calendar#FRIDAY
    375      * @see Calendar#SATURDAY
    376      *
    377      * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
    378      */
    379     public int getFirstDayOfWeek() {
    380         return mDelegate.getFirstDayOfWeek();
    381     }
    382 
    383     /**
    384      * Returns whether the {@link CalendarView} is shown.
    385      * <p>
    386      * <strong>Note:</strong> This method returns {@code false} when the
    387      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
    388      * to {@code calendar}.
    389      *
    390      * @return {@code true} if the calendar view is shown
    391      * @see #getCalendarView()
    392      * @deprecated Not supported by Material-style {@code calendar} mode
    393      */
    394     @Deprecated
    395     public boolean getCalendarViewShown() {
    396         return mDelegate.getCalendarViewShown();
    397     }
    398 
    399     /**
    400      * Returns the {@link CalendarView} used by this picker.
    401      * <p>
    402      * <strong>Note:</strong> This method throws an
    403      * {@link UnsupportedOperationException} when the
    404      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
    405      * to {@code calendar}.
    406      *
    407      * @return the calendar view
    408      * @see #getCalendarViewShown()
    409      * @deprecated Not supported by Material-style {@code calendar} mode
    410      * @throws UnsupportedOperationException if called when the picker is
    411      *         displayed in {@code calendar} mode
    412      */
    413     @Deprecated
    414     public CalendarView getCalendarView() {
    415         return mDelegate.getCalendarView();
    416     }
    417 
    418     /**
    419      * Sets whether the {@link CalendarView} is shown.
    420      * <p>
    421      * <strong>Note:</strong> Calling this method has no effect when the
    422      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
    423      * to {@code calendar}.
    424      *
    425      * @param shown {@code true} to show the calendar view, {@code false} to
    426      *              hide it
    427      * @deprecated Not supported by Material-style {@code calendar} mode
    428      */
    429     @Deprecated
    430     public void setCalendarViewShown(boolean shown) {
    431         mDelegate.setCalendarViewShown(shown);
    432     }
    433 
    434     /**
    435      * Returns whether the spinners are shown.
    436      * <p>
    437      * <strong>Note:</strong> his method returns {@code false} when the
    438      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
    439      * to {@code calendar}.
    440      *
    441      * @return {@code true} if the spinners are shown
    442      * @deprecated Not supported by Material-style {@code calendar} mode
    443      */
    444     @Deprecated
    445     public boolean getSpinnersShown() {
    446         return mDelegate.getSpinnersShown();
    447     }
    448 
    449     /**
    450      * Sets whether the spinners are shown.
    451      * <p>
    452      * Calling this method has no effect when the
    453      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
    454      * to {@code calendar}.
    455      *
    456      * @param shown {@code true} to show the spinners, {@code false} to hide
    457      *              them
    458      * @deprecated Not supported by Material-style {@code calendar} mode
    459      */
    460     @Deprecated
    461     public void setSpinnersShown(boolean shown) {
    462         mDelegate.setSpinnersShown(shown);
    463     }
    464 
    465     @Override
    466     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
    467         dispatchThawSelfOnly(container);
    468     }
    469 
    470     @Override
    471     protected Parcelable onSaveInstanceState() {
    472         Parcelable superState = super.onSaveInstanceState();
    473         return mDelegate.onSaveInstanceState(superState);
    474     }
    475 
    476     @Override
    477     protected void onRestoreInstanceState(Parcelable state) {
    478         BaseSavedState ss = (BaseSavedState) state;
    479         super.onRestoreInstanceState(ss.getSuperState());
    480         mDelegate.onRestoreInstanceState(ss);
    481     }
    482 
    483     /**
    484      * A delegate interface that defined the public API of the DatePicker. Allows different
    485      * DatePicker implementations. This would need to be implemented by the DatePicker delegates
    486      * for the real behavior.
    487      *
    488      * @hide
    489      */
    490     interface DatePickerDelegate {
    491         void init(int year, int monthOfYear, int dayOfMonth,
    492                   OnDateChangedListener onDateChangedListener);
    493 
    494         void updateDate(int year, int month, int dayOfMonth);
    495 
    496         int getYear();
    497         int getMonth();
    498         int getDayOfMonth();
    499 
    500         void setFirstDayOfWeek(int firstDayOfWeek);
    501         int getFirstDayOfWeek();
    502 
    503         void setMinDate(long minDate);
    504         Calendar getMinDate();
    505 
    506         void setMaxDate(long maxDate);
    507         Calendar getMaxDate();
    508 
    509         void setEnabled(boolean enabled);
    510         boolean isEnabled();
    511 
    512         CalendarView getCalendarView();
    513 
    514         void setCalendarViewShown(boolean shown);
    515         boolean getCalendarViewShown();
    516 
    517         void setSpinnersShown(boolean shown);
    518         boolean getSpinnersShown();
    519 
    520         void setValidationCallback(ValidationCallback callback);
    521 
    522         void onConfigurationChanged(Configuration newConfig);
    523 
    524         Parcelable onSaveInstanceState(Parcelable superState);
    525         void onRestoreInstanceState(Parcelable state);
    526 
    527         boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
    528         void onPopulateAccessibilityEvent(AccessibilityEvent event);
    529     }
    530 
    531     /**
    532      * An abstract class which can be used as a start for DatePicker implementations
    533      */
    534     abstract static class AbstractDatePickerDelegate implements DatePickerDelegate {
    535         // The delegator
    536         protected DatePicker mDelegator;
    537 
    538         // The context
    539         protected Context mContext;
    540 
    541         // The current locale
    542         protected Locale mCurrentLocale;
    543 
    544         // Callbacks
    545         protected OnDateChangedListener mOnDateChangedListener;
    546         protected ValidationCallback mValidationCallback;
    547 
    548         public AbstractDatePickerDelegate(DatePicker delegator, Context context) {
    549             mDelegator = delegator;
    550             mContext = context;
    551 
    552             setCurrentLocale(Locale.getDefault());
    553         }
    554 
    555         protected void setCurrentLocale(Locale locale) {
    556             if (!locale.equals(mCurrentLocale)) {
    557                 mCurrentLocale = locale;
    558                 onLocaleChanged(locale);
    559             }
    560         }
    561 
    562         @Override
    563         public void setValidationCallback(ValidationCallback callback) {
    564             mValidationCallback = callback;
    565         }
    566 
    567         protected void onValidationChanged(boolean valid) {
    568             if (mValidationCallback != null) {
    569                 mValidationCallback.onValidationChanged(valid);
    570             }
    571         }
    572 
    573         protected void onLocaleChanged(Locale locale) {
    574             // Stub.
    575         }
    576 
    577         /**
    578          * Class for managing state storing/restoring.
    579          */
    580         static class SavedState extends View.BaseSavedState {
    581             private final int mSelectedYear;
    582             private final int mSelectedMonth;
    583             private final int mSelectedDay;
    584             private final long mMinDate;
    585             private final long mMaxDate;
    586             private final int mCurrentView;
    587             private final int mListPosition;
    588             private final int mListPositionOffset;
    589 
    590             public SavedState(Parcelable superState, int year, int month, int day, long minDate,
    591                     long maxDate) {
    592                 this(superState, year, month, day, minDate, maxDate, 0, 0, 0);
    593             }
    594 
    595             /**
    596              * Constructor called from {@link DatePicker#onSaveInstanceState()}
    597              */
    598             public SavedState(Parcelable superState, int year, int month, int day, long minDate,
    599                     long maxDate, int currentView, int listPosition, int listPositionOffset) {
    600                 super(superState);
    601                 mSelectedYear = year;
    602                 mSelectedMonth = month;
    603                 mSelectedDay = day;
    604                 mMinDate = minDate;
    605                 mMaxDate = maxDate;
    606                 mCurrentView = currentView;
    607                 mListPosition = listPosition;
    608                 mListPositionOffset = listPositionOffset;
    609             }
    610 
    611             /**
    612              * Constructor called from {@link #CREATOR}
    613              */
    614             private SavedState(Parcel in) {
    615                 super(in);
    616                 mSelectedYear = in.readInt();
    617                 mSelectedMonth = in.readInt();
    618                 mSelectedDay = in.readInt();
    619                 mMinDate = in.readLong();
    620                 mMaxDate = in.readLong();
    621                 mCurrentView = in.readInt();
    622                 mListPosition = in.readInt();
    623                 mListPositionOffset = in.readInt();
    624             }
    625 
    626             @Override
    627             public void writeToParcel(Parcel dest, int flags) {
    628                 super.writeToParcel(dest, flags);
    629                 dest.writeInt(mSelectedYear);
    630                 dest.writeInt(mSelectedMonth);
    631                 dest.writeInt(mSelectedDay);
    632                 dest.writeLong(mMinDate);
    633                 dest.writeLong(mMaxDate);
    634                 dest.writeInt(mCurrentView);
    635                 dest.writeInt(mListPosition);
    636                 dest.writeInt(mListPositionOffset);
    637             }
    638 
    639             public int getSelectedDay() {
    640                 return mSelectedDay;
    641             }
    642 
    643             public int getSelectedMonth() {
    644                 return mSelectedMonth;
    645             }
    646 
    647             public int getSelectedYear() {
    648                 return mSelectedYear;
    649             }
    650 
    651             public long getMinDate() {
    652                 return mMinDate;
    653             }
    654 
    655             public long getMaxDate() {
    656                 return mMaxDate;
    657             }
    658 
    659             public int getCurrentView() {
    660                 return mCurrentView;
    661             }
    662 
    663             public int getListPosition() {
    664                 return mListPosition;
    665             }
    666 
    667             public int getListPositionOffset() {
    668                 return mListPositionOffset;
    669             }
    670 
    671             @SuppressWarnings("all")
    672             // suppress unused and hiding
    673             public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
    674 
    675                 public SavedState createFromParcel(Parcel in) {
    676                     return new SavedState(in);
    677                 }
    678 
    679                 public SavedState[] newArray(int size) {
    680                     return new SavedState[size];
    681                 }
    682             };
    683         }
    684     }
    685 
    686     /**
    687      * A callback interface for updating input validity when the date picker
    688      * when included into a dialog.
    689      *
    690      * @hide
    691      */
    692     public interface ValidationCallback {
    693         void onValidationChanged(boolean valid);
    694     }
    695 }
    696