Home | History | Annotate | Download | only in app
      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.app;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.StyleRes;
     22 import android.annotation.UnsupportedAppUsage;
     23 import android.content.Context;
     24 import android.content.DialogInterface;
     25 import android.content.DialogInterface.OnClickListener;
     26 import android.os.Bundle;
     27 import android.util.TypedValue;
     28 import android.view.LayoutInflater;
     29 import android.view.View;
     30 import android.widget.Button;
     31 import android.widget.DatePicker;
     32 import android.widget.DatePicker.OnDateChangedListener;
     33 import android.widget.DatePicker.ValidationCallback;
     34 
     35 import com.android.internal.R;
     36 
     37 import java.util.Calendar;
     38 
     39 /**
     40  * A simple dialog containing an {@link android.widget.DatePicker}.
     41  * <p>
     42  * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
     43  * guide.
     44  */
     45 public class DatePickerDialog extends AlertDialog implements OnClickListener,
     46         OnDateChangedListener {
     47     private static final String YEAR = "year";
     48     private static final String MONTH = "month";
     49     private static final String DAY = "day";
     50 
     51     @UnsupportedAppUsage
     52     private final DatePicker mDatePicker;
     53 
     54     private OnDateSetListener mDateSetListener;
     55 
     56     /**
     57      * Creates a new date picker dialog for the current date using the parent
     58      * context's default date picker dialog theme.
     59      *
     60      * @param context the parent context
     61      */
     62     public DatePickerDialog(@NonNull Context context) {
     63         this(context, 0, null, Calendar.getInstance(), -1, -1, -1);
     64     }
     65 
     66     /**
     67      * Creates a new date picker dialog for the current date.
     68      *
     69      * @param context the parent context
     70      * @param themeResId the resource ID of the theme against which to inflate
     71      *                   this dialog, or {@code 0} to use the parent
     72      *                   {@code context}'s default alert dialog theme
     73      */
     74     public DatePickerDialog(@NonNull Context context, @StyleRes int themeResId) {
     75         this(context, themeResId, null, Calendar.getInstance(), -1, -1, -1);
     76     }
     77 
     78     /**
     79      * Creates a new date picker dialog for the specified date using the parent
     80      * context's default date picker dialog theme.
     81      *
     82      * @param context the parent context
     83      * @param listener the listener to call when the user sets the date
     84      * @param year the initially selected year
     85      * @param month the initially selected month (0-11 for compatibility with
     86      *              {@link Calendar#MONTH})
     87      * @param dayOfMonth the initially selected day of month (1-31, depending
     88      *                   on month)
     89      */
     90     public DatePickerDialog(@NonNull Context context, @Nullable OnDateSetListener listener,
     91             int year, int month, int dayOfMonth) {
     92         this(context, 0, listener, null, year, month, dayOfMonth);
     93     }
     94 
     95     /**
     96      * Creates a new date picker dialog for the specified date.
     97      *
     98      * @param context the parent context
     99      * @param themeResId the resource ID of the theme against which to inflate
    100      *                   this dialog, or {@code 0} to use the parent
    101      *                   {@code context}'s default alert dialog theme
    102      * @param listener the listener to call when the user sets the date
    103      * @param year the initially selected year
    104      * @param monthOfYear the initially selected month of the year (0-11 for
    105      *                    compatibility with {@link Calendar#MONTH})
    106      * @param dayOfMonth the initially selected day of month (1-31, depending
    107      *                   on month)
    108      */
    109     public DatePickerDialog(@NonNull Context context, @StyleRes int themeResId,
    110             @Nullable OnDateSetListener listener, int year, int monthOfYear, int dayOfMonth) {
    111         this(context, themeResId, listener, null, year, monthOfYear, dayOfMonth);
    112     }
    113 
    114     private DatePickerDialog(@NonNull Context context, @StyleRes int themeResId,
    115             @Nullable OnDateSetListener listener, @Nullable Calendar calendar, int year,
    116             int monthOfYear, int dayOfMonth) {
    117         super(context, resolveDialogTheme(context, themeResId));
    118 
    119         final Context themeContext = getContext();
    120         final LayoutInflater inflater = LayoutInflater.from(themeContext);
    121         final View view = inflater.inflate(R.layout.date_picker_dialog, null);
    122         setView(view);
    123 
    124         setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this);
    125         setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this);
    126         setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
    127 
    128         if (calendar != null) {
    129             year = calendar.get(Calendar.YEAR);
    130             monthOfYear = calendar.get(Calendar.MONTH);
    131             dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
    132         }
    133 
    134         mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
    135         mDatePicker.init(year, monthOfYear, dayOfMonth, this);
    136         mDatePicker.setValidationCallback(mValidationCallback);
    137 
    138         mDateSetListener = listener;
    139     }
    140 
    141     static @StyleRes int resolveDialogTheme(@NonNull Context context, @StyleRes int themeResId) {
    142         if (themeResId == 0) {
    143             final TypedValue outValue = new TypedValue();
    144             context.getTheme().resolveAttribute(R.attr.datePickerDialogTheme, outValue, true);
    145             return outValue.resourceId;
    146         } else {
    147             return themeResId;
    148         }
    149     }
    150 
    151     @Override
    152     public void onDateChanged(@NonNull DatePicker view, int year, int month, int dayOfMonth) {
    153         mDatePicker.init(year, month, dayOfMonth, this);
    154     }
    155 
    156     /**
    157      * Sets the listener to call when the user sets the date.
    158      *
    159      * @param listener the listener to call when the user sets the date
    160      */
    161     public void setOnDateSetListener(@Nullable OnDateSetListener listener) {
    162         mDateSetListener = listener;
    163     }
    164 
    165     @Override
    166     public void onClick(@NonNull DialogInterface dialog, int which) {
    167         switch (which) {
    168             case BUTTON_POSITIVE:
    169                 if (mDateSetListener != null) {
    170                     // Clearing focus forces the dialog to commit any pending
    171                     // changes, e.g. typed text in a NumberPicker.
    172                     mDatePicker.clearFocus();
    173                     mDateSetListener.onDateSet(mDatePicker, mDatePicker.getYear(),
    174                             mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
    175                 }
    176                 break;
    177             case BUTTON_NEGATIVE:
    178                 cancel();
    179                 break;
    180         }
    181     }
    182 
    183     /**
    184      * Returns the {@link DatePicker} contained in this dialog.
    185      *
    186      * @return the date picker
    187      */
    188     @NonNull
    189     public DatePicker getDatePicker() {
    190         return mDatePicker;
    191     }
    192 
    193     /**
    194      * Sets the current date.
    195      *
    196      * @param year the year
    197      * @param month the month (0-11 for compatibility with
    198      *              {@link Calendar#MONTH})
    199      * @param dayOfMonth the day of month (1-31, depending on month)
    200      */
    201     public void updateDate(int year, int month, int dayOfMonth) {
    202         mDatePicker.updateDate(year, month, dayOfMonth);
    203     }
    204 
    205     @Override
    206     public Bundle onSaveInstanceState() {
    207         final Bundle state = super.onSaveInstanceState();
    208         state.putInt(YEAR, mDatePicker.getYear());
    209         state.putInt(MONTH, mDatePicker.getMonth());
    210         state.putInt(DAY, mDatePicker.getDayOfMonth());
    211         return state;
    212     }
    213 
    214     @Override
    215     public void onRestoreInstanceState(Bundle savedInstanceState) {
    216         super.onRestoreInstanceState(savedInstanceState);
    217         final int year = savedInstanceState.getInt(YEAR);
    218         final int month = savedInstanceState.getInt(MONTH);
    219         final int day = savedInstanceState.getInt(DAY);
    220         mDatePicker.init(year, month, day, this);
    221     }
    222 
    223     private final ValidationCallback mValidationCallback = new ValidationCallback() {
    224         @Override
    225         public void onValidationChanged(boolean valid) {
    226             final Button positive = getButton(BUTTON_POSITIVE);
    227             if (positive != null) {
    228                 positive.setEnabled(valid);
    229             }
    230         }
    231     };
    232 
    233     /**
    234      * The listener used to indicate the user has finished selecting a date.
    235      */
    236     public interface OnDateSetListener {
    237         /**
    238          * @param view the picker associated with the dialog
    239          * @param year the selected year
    240          * @param month the selected month (0-11 for compatibility with
    241          *              {@link Calendar#MONTH})
    242          * @param dayOfMonth the selected day of the month (1-31, depending on
    243          *                   month)
    244          */
    245         void onDateSet(DatePicker view, int year, int month, int dayOfMonth);
    246     }
    247 }
    248