blob: 8e4ba0d65352dafd31d27f34a7ce1222d380c00d [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.widget;
18
19import android.annotation.Widget;
20import android.content.Context;
Svetoslav Ganovf5926962011-07-12 12:26:20 -070021import android.content.res.Configuration;
Svetoslav Ganov4243dc32011-01-18 19:39:57 -080022import android.content.res.TypedArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.Parcelable;
24import android.util.AttributeSet;
Svetoslav Ganov8a2a8952011-01-27 17:40:13 -080025import android.view.accessibility.AccessibilityEvent;
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -080026import android.view.accessibility.AccessibilityNodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
Svetoslav Ganova53efe92011-09-08 18:08:36 -070028import com.android.internal.R;
29
Svetoslav Ganovf5926962011-07-12 12:26:20 -070030import java.util.Locale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -070032import static android.os.Build.VERSION_CODES.KITKAT;
33
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034/**
Svetoslav Ganov4243dc32011-01-18 19:39:57 -080035 * A view for selecting the time of day, in either 24 hour or AM/PM mode. The
36 * hour, each minute digit, and AM/PM (if applicable) can be conrolled by
37 * vertical spinners. The hour can be entered by keyboard input. Entering in two
38 * digit hours can be accomplished by hitting two digits within a timeout of
39 * about a second (e.g. '1' then '2' to select 12). The minutes can be entered
40 * by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p'
41 * or 'P' to pick. For a dialog using this view, see
42 * {@link android.app.TimePickerDialog}.
43 *<p>
Scott Main4c359b72012-07-24 15:51:27 -070044 * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
45 * guide.
Svetoslav Ganov4243dc32011-01-18 19:39:57 -080046 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 */
48@Widget
49public class TimePicker extends FrameLayout {
Svetoslav Ganov206316a2010-11-19 00:04:05 -080050
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -070051 private TimePickerDelegate mDelegate;
Fabrice Di Meglio64902bd2013-08-15 17:49:49 -070052
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -070053 private AttributeSet mAttrs;
54 private int mDefStyleAttr;
55 private int mDefStyleRes;
56 private Context mContext;
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 /**
59 * The callback interface used to indicate the time has been adjusted.
60 */
61 public interface OnTimeChangedListener {
62
63 /**
64 * @param view The view associated with this listener.
65 * @param hourOfDay The current hour.
66 * @param minute The current minute.
67 */
68 void onTimeChanged(TimePicker view, int hourOfDay, int minute);
69 }
70
71 public TimePicker(Context context) {
72 this(context, null);
73 }
Svetoslav Ganov4243dc32011-01-18 19:39:57 -080074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 public TimePicker(Context context, AttributeSet attrs) {
Svetoslav Ganov4243dc32011-01-18 19:39:57 -080076 this(context, attrs, R.attr.timePickerStyle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 }
78
Alan Viverette617feb92013-09-09 18:09:13 -070079 public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
80 this(context, attrs, defStyleAttr, 0);
81 }
82
83 public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
84 super(context, attrs, defStyleAttr, defStyleRes);
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -070085
86 mContext = context;
87 mAttrs = attrs;
88 mDefStyleAttr = defStyleAttr;
89 mDefStyleRes = defStyleRes;
90
91 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePicker,
92 mDefStyleAttr, mDefStyleRes);
93
94 // Create the correct UI delegate. Default is the legacy one.
95 final boolean isLegacyMode = shouldForceLegacyMode() ?
96 true : a.getBoolean(R.styleable.TimePicker_legacyMode, true);
97 setLegacyMode(isLegacyMode);
98 }
99
100 private boolean shouldForceLegacyMode() {
101 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
102 return targetSdkVersion < KITKAT;
103 }
104
105 private TimePickerDelegate createLegacyUIDelegate(Context context, AttributeSet attrs,
106 int defStyleAttr, int defStyleRes) {
107 return new LegacyTimePickerDelegate(this, context, attrs, defStyleAttr, defStyleRes);
108 }
109
110 private TimePickerDelegate createNewUIDelegate(Context context, AttributeSet attrs,
111 int defStyleAttr, int defStyleRes) {
112 return new android.widget.TimePickerDelegate(this, context, attrs, defStyleAttr,
113 defStyleRes);
114 }
115
116 /**
117 * @hide
118 */
119 public void setLegacyMode(boolean isLegacyMode) {
120 removeAllViewsInLayout();
121 mDelegate = isLegacyMode ?
122 createLegacyUIDelegate(mContext, mAttrs, mDefStyleAttr, mDefStyleRes) :
123 createNewUIDelegate(mContext, mAttrs, mDefStyleAttr, mDefStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 }
Svetoslav Ganov50f34d12010-12-03 16:05:40 -0800125
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700126 /**
127 * Set the current hour.
128 */
129 public void setCurrentHour(Integer currentHour) {
130 mDelegate.setCurrentHour(currentHour);
Fabrice Di Meglio64902bd2013-08-15 17:49:49 -0700131 }
132
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700133 /**
134 * @return The current hour in the range (0-23).
135 */
136 public Integer getCurrentHour() {
137 return mDelegate.getCurrentHour();
138 }
Fabrice Di Meglio64902bd2013-08-15 17:49:49 -0700139
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700140 /**
141 * Set the current minute (0-59).
142 */
143 public void setCurrentMinute(Integer currentMinute) {
144 mDelegate.setCurrentMinute(currentMinute);
145 }
146
147 /**
148 * @return The current minute.
149 */
150 public Integer getCurrentMinute() {
151 return mDelegate.getCurrentMinute();
152 }
153
154 /**
155 * Set whether in 24 hour or AM/PM mode.
156 *
157 * @param is24HourView True = 24 hour mode. False = AM/PM.
158 */
159 public void setIs24HourView(Boolean is24HourView) {
160 mDelegate.setIs24HourView(is24HourView);
161 }
162
163 /**
164 * @return true if this is in 24 hour view else false.
165 */
166 public boolean is24HourView() {
167 return mDelegate.is24HourView();
168 }
169
170 /**
171 * Set the callback that indicates the time has been adjusted by the user.
172 *
173 * @param onTimeChangedListener the callback, should not be null.
174 */
175 public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
176 mDelegate.setOnTimeChangedListener(onTimeChangedListener);
Fabrice Di Meglio64902bd2013-08-15 17:49:49 -0700177 }
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 @Override
180 public void setEnabled(boolean enabled) {
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700181 if (mDelegate.isEnabled() == enabled) {
Svetoslav Ganov51c52ed2010-12-28 13:45:03 -0800182 return;
183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 super.setEnabled(enabled);
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700185 mDelegate.setEnabled(enabled);
Svetoslav Ganov51c52ed2010-12-28 13:45:03 -0800186 }
187
188 @Override
189 public boolean isEnabled() {
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700190 return mDelegate.isEnabled();
191 }
192
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700193 /**
194 * @hide
195 */
196 public void setShowDoneButton(boolean showDoneButton) {
197 mDelegate.setShowDoneButton(showDoneButton);
198 }
199
200 /**
201 * @hide
202 */
203 public void setDismissCallback(TimePickerDismissCallback callback) {
204 mDelegate.setDismissCallback(callback);
205 }
206
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700207 @Override
208 public int getBaseline() {
209 return mDelegate.getBaseline();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 }
211
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700212 @Override
213 protected void onConfigurationChanged(Configuration newConfig) {
214 super.onConfigurationChanged(newConfig);
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700215 mDelegate.onConfigurationChanged(newConfig);
216 }
217
218 @Override
219 protected Parcelable onSaveInstanceState() {
220 Parcelable superState = super.onSaveInstanceState();
221 return mDelegate.onSaveInstanceState(superState);
222 }
223
224 @Override
225 protected void onRestoreInstanceState(Parcelable state) {
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700226 BaseSavedState ss = (BaseSavedState) state;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700227 super.onRestoreInstanceState(ss.getSuperState());
228 mDelegate.onRestoreInstanceState(ss);
229 }
230
231 @Override
232 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
233 return mDelegate.dispatchPopulateAccessibilityEvent(event);
234 }
235
236 @Override
237 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
238 super.onPopulateAccessibilityEvent(event);
239 mDelegate.onPopulateAccessibilityEvent(event);
240 }
241
242 @Override
243 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
244 super.onInitializeAccessibilityEvent(event);
245 mDelegate.onInitializeAccessibilityEvent(event);
246 }
247
248 @Override
249 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
250 super.onInitializeAccessibilityNodeInfo(info);
251 mDelegate.onInitializeAccessibilityNodeInfo(info);
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700252 }
253
254 /**
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700255 * A delegate interface that defined the public API of the TimePicker. Allows different
256 * TimePicker implementations. This would need to be implemented by the TimePicker delegates
257 * for the real behavior.
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700258 */
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700259 interface TimePickerDelegate {
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700260 void setCurrentHour(Integer currentHour);
261 Integer getCurrentHour();
262
263 void setCurrentMinute(Integer currentMinute);
264 Integer getCurrentMinute();
265
266 void setIs24HourView(Boolean is24HourView);
267 boolean is24HourView();
268
269 void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
270
271 void setEnabled(boolean enabled);
272 boolean isEnabled();
273
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700274 void setShowDoneButton(boolean showDoneButton);
275 void setDismissCallback(TimePickerDismissCallback callback);
276
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700277 int getBaseline();
278
279 void onConfigurationChanged(Configuration newConfig);
280
281 Parcelable onSaveInstanceState(Parcelable superState);
282 void onRestoreInstanceState(Parcelable state);
283
284 boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
285 void onPopulateAccessibilityEvent(AccessibilityEvent event);
286 void onInitializeAccessibilityEvent(AccessibilityEvent event);
287 void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
288 }
289
290 /**
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700291 * A callback interface for dismissing the TimePicker when included into a Dialog
292 *
293 * @hide
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700294 */
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700295 public static interface TimePickerDismissCallback {
296 void dismiss(TimePicker view, boolean isCancel, int hourOfDay, int minute);
297 }
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700298
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700299 /**
300 * An abstract class which can be used as a start for TimePicker implementations
301 */
302 abstract static class AbstractTimePickerDelegate implements TimePickerDelegate {
303 // The delegator
304 protected TimePicker mDelegator;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700305
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700306 // The context
307 protected Context mContext;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700308
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700309 // The current locale
310 protected Locale mCurrentLocale;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700311
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700312 // Callbacks
313 protected OnTimeChangedListener mOnTimeChangedListener;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700314
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700315 public AbstractTimePickerDelegate(TimePicker delegator, Context context) {
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700316 mDelegator = delegator;
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700317 mContext = context;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700318
319 // initialization based on locale
320 setCurrentLocale(Locale.getDefault());
Svetoslav Ganovf5926962011-07-12 12:26:20 -0700321 }
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700322
Fabrice Di Meglioeeff63a2013-08-05 12:07:24 -0700323 public void setCurrentLocale(Locale locale) {
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700324 if (locale.equals(mCurrentLocale)) {
325 return;
326 }
327 mCurrentLocale = locale;
Fabrice Di Meglio9e4009e2013-08-19 13:16:46 -0700328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330}