blob: 195c3e1c296a5cf8c3e49af130fd1b87fa8cdc28 [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
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.app;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.StyleRes;
22import android.compat.annotation.UnsupportedAppUsage;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.DialogInterface.OnClickListener;
26import android.os.Bundle;
27import android.util.TypedValue;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.widget.Button;
31import android.widget.DatePicker;
32import android.widget.DatePicker.OnDateChangedListener;
33import android.widget.DatePicker.ValidationCallback;
34
35import com.android.internal.R;
36
37import 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 */
45public 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}