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.TestApi;
20 import android.content.Context;
21 import android.content.DialogInterface;
22 import android.content.DialogInterface.OnClickListener;
23 import android.os.Bundle;
24 import android.util.TypedValue;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.widget.TimePicker;
28 import android.widget.TimePicker.OnTimeChangedListener;
29 
30 import com.android.internal.R;
31 
32 /**
33  * A dialog that prompts the user for the time of day using a
34  * {@link TimePicker}.
35  *
36  * <p>
37  * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
38  * guide.
39  */
40 public class TimePickerDialog extends AlertDialog implements OnClickListener,
41         OnTimeChangedListener {
42     private static final String HOUR = "hour";
43     private static final String MINUTE = "minute";
44     private static final String IS_24_HOUR = "is24hour";
45 
46     private final TimePicker mTimePicker;
47     private final OnTimeSetListener mTimeSetListener;
48 
49     private final int mInitialHourOfDay;
50     private final int mInitialMinute;
51     private final boolean mIs24HourView;
52 
53     /**
54      * The callback interface used to indicate the user is done filling in
55      * the time (e.g. they clicked on the 'OK' button).
56      */
57     public interface OnTimeSetListener {
58         /**
59          * Called when the user is done setting a new time and the dialog has
60          * closed.
61          *
62          * @param view the view associated with this listener
63          * @param hourOfDay the hour that was set
64          * @param minute the minute that was set
65          */
onTimeSet(TimePicker view, int hourOfDay, int minute)66         void onTimeSet(TimePicker view, int hourOfDay, int minute);
67     }
68 
69     /**
70      * Creates a new time picker dialog.
71      *
72      * @param context the parent context
73      * @param listener the listener to call when the time is set
74      * @param hourOfDay the initial hour
75      * @param minute the initial minute
76      * @param is24HourView whether this is a 24 hour view or AM/PM
77      */
TimePickerDialog(Context context, OnTimeSetListener listener, int hourOfDay, int minute, boolean is24HourView)78     public TimePickerDialog(Context context, OnTimeSetListener listener, int hourOfDay, int minute,
79             boolean is24HourView) {
80         this(context, 0, listener, hourOfDay, minute, is24HourView);
81     }
82 
resolveDialogTheme(Context context, int resId)83     static int resolveDialogTheme(Context context, int resId) {
84         if (resId == 0) {
85             final TypedValue outValue = new TypedValue();
86             context.getTheme().resolveAttribute(R.attr.timePickerDialogTheme, outValue, true);
87             return outValue.resourceId;
88         } else {
89             return resId;
90         }
91     }
92 
93     /**
94      * Creates a new time picker dialog with the specified theme.
95      * <p>
96      * The theme is overlaid on top of the theme of the parent {@code context}.
97      * If {@code themeResId} is 0, the dialog will be inflated using the theme
98      * specified by the
99      * {@link android.R.attr#timePickerDialogTheme android:timePickerDialogTheme}
100      * attribute on the parent {@code context}'s theme.
101      *
102      * @param context the parent context
103      * @param themeResId the resource ID of the theme to apply to this dialog
104      * @param listener the listener to call when the time is set
105      * @param hourOfDay the initial hour
106      * @param minute the initial minute
107      * @param is24HourView Whether this is a 24 hour view, or AM/PM.
108      */
TimePickerDialog(Context context, int themeResId, OnTimeSetListener listener, int hourOfDay, int minute, boolean is24HourView)109     public TimePickerDialog(Context context, int themeResId, OnTimeSetListener listener,
110             int hourOfDay, int minute, boolean is24HourView) {
111         super(context, resolveDialogTheme(context, themeResId));
112 
113         mTimeSetListener = listener;
114         mInitialHourOfDay = hourOfDay;
115         mInitialMinute = minute;
116         mIs24HourView = is24HourView;
117 
118         final Context themeContext = getContext();
119         final LayoutInflater inflater = LayoutInflater.from(themeContext);
120         final View view = inflater.inflate(R.layout.time_picker_dialog, null);
121         setView(view);
122         setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this);
123         setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this);
124         setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
125 
126         mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
127         mTimePicker.setIs24HourView(mIs24HourView);
128         mTimePicker.setCurrentHour(mInitialHourOfDay);
129         mTimePicker.setCurrentMinute(mInitialMinute);
130         mTimePicker.setOnTimeChangedListener(this);
131     }
132 
133     /**
134      * @return the time picker displayed in the dialog
135      * @hide For testing only.
136      */
137     @TestApi
getTimePicker()138     public TimePicker getTimePicker() {
139         return mTimePicker;
140     }
141 
142     @Override
onTimeChanged(TimePicker view, int hourOfDay, int minute)143     public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
144         /* do nothing */
145     }
146 
147     @Override
show()148     public void show() {
149         super.show();
150         getButton(BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
151             @Override
152             public void onClick(View view) {
153                 if (mTimePicker.validateInput()) {
154                     TimePickerDialog.this.onClick(TimePickerDialog.this, BUTTON_POSITIVE);
155                     dismiss();
156                 }
157             }
158         });
159     }
160 
161     @Override
onClick(DialogInterface dialog, int which)162     public void onClick(DialogInterface dialog, int which) {
163         switch (which) {
164             case BUTTON_POSITIVE:
165                 // Note this skips input validation and just uses the last valid time and hour
166                 // entry. This will only be invoked programmatically. User clicks on BUTTON_POSITIVE
167                 // are handled in show().
168                 if (mTimeSetListener != null) {
169                     mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
170                             mTimePicker.getCurrentMinute());
171                 }
172                 break;
173             case BUTTON_NEGATIVE:
174                 cancel();
175                 break;
176         }
177     }
178 
179     /**
180      * Sets the current time.
181      *
182      * @param hourOfDay The current hour within the day.
183      * @param minuteOfHour The current minute within the hour.
184      */
updateTime(int hourOfDay, int minuteOfHour)185     public void updateTime(int hourOfDay, int minuteOfHour) {
186         mTimePicker.setCurrentHour(hourOfDay);
187         mTimePicker.setCurrentMinute(minuteOfHour);
188     }
189 
190     @Override
onSaveInstanceState()191     public Bundle onSaveInstanceState() {
192         final Bundle state = super.onSaveInstanceState();
193         state.putInt(HOUR, mTimePicker.getCurrentHour());
194         state.putInt(MINUTE, mTimePicker.getCurrentMinute());
195         state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
196         return state;
197     }
198 
199     @Override
onRestoreInstanceState(Bundle savedInstanceState)200     public void onRestoreInstanceState(Bundle savedInstanceState) {
201         super.onRestoreInstanceState(savedInstanceState);
202         final int hour = savedInstanceState.getInt(HOUR);
203         final int minute = savedInstanceState.getInt(MINUTE);
204         mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
205         mTimePicker.setCurrentHour(hour);
206         mTimePicker.setCurrentMinute(minute);
207     }
208 }
209