TimePicker.java revision daf33ed85353ab7d7a7668dd0e3f9a66f0d5583f
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
17package android.widget;
18
19import android.annotation.Nullable;
20import android.annotation.Widget;
21import android.content.Context;
22import android.content.res.Configuration;
23import android.content.res.TypedArray;
24import android.os.Parcelable;
25import android.util.AttributeSet;
26import android.view.accessibility.AccessibilityEvent;
27import android.view.accessibility.AccessibilityNodeInfo;
28
29import com.android.internal.R;
30
31import java.util.Locale;
32
33/**
34 * A view for selecting the time of day, in either 24 hour or AM/PM mode. The
35 * hour, each minute digit, and AM/PM (if applicable) can be conrolled by
36 * vertical spinners. The hour can be entered by keyboard input. Entering in two
37 * digit hours can be accomplished by hitting two digits within a timeout of
38 * about a second (e.g. '1' then '2' to select 12). The minutes can be entered
39 * by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p'
40 * or 'P' to pick. For a dialog using this view, see
41 * {@link android.app.TimePickerDialog}.
42 * <p>
43 * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
44 * guide.
45 * </p>
46 */
47@Widget
48public class TimePicker extends FrameLayout {
49    private static final int MODE_SPINNER = 1;
50    private static final int MODE_CLOCK = 2;
51
52    private final TimePickerDelegate mDelegate;
53
54    /**
55     * The callback interface used to indicate the time has been adjusted.
56     */
57    public interface OnTimeChangedListener {
58
59        /**
60         * @param view The view associated with this listener.
61         * @param hourOfDay The current hour.
62         * @param minute The current minute.
63         */
64        void onTimeChanged(TimePicker view, int hourOfDay, int minute);
65    }
66
67    public TimePicker(Context context) {
68        this(context, null);
69    }
70
71    public TimePicker(Context context, AttributeSet attrs) {
72        this(context, attrs, R.attr.timePickerStyle);
73    }
74
75    public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
76        this(context, attrs, defStyleAttr, 0);
77    }
78
79    public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
80        super(context, attrs, defStyleAttr, defStyleRes);
81
82        final TypedArray a = context.obtainStyledAttributes(
83                attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
84        final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
85        a.recycle();
86
87        switch (mode) {
88            case MODE_CLOCK:
89                mDelegate = new TimePickerClockDelegate(
90                        this, context, attrs, defStyleAttr, defStyleRes);
91                break;
92            case MODE_SPINNER:
93            default:
94                mDelegate = new TimePickerSpinnerDelegate(
95                        this, context, attrs, defStyleAttr, defStyleRes);
96                break;
97        }
98    }
99
100    /**
101     * Set the current hour.
102     */
103    public void setCurrentHour(Integer currentHour) {
104        mDelegate.setCurrentHour(currentHour);
105    }
106
107    /**
108     * @return The current hour in the range (0-23).
109     */
110    public Integer getCurrentHour() {
111        return mDelegate.getCurrentHour();
112    }
113
114    /**
115     * Set the current minute (0-59).
116     */
117    public void setCurrentMinute(Integer currentMinute) {
118        mDelegate.setCurrentMinute(currentMinute);
119    }
120
121    /**
122     * @return The current minute.
123     */
124    public Integer getCurrentMinute() {
125        return mDelegate.getCurrentMinute();
126    }
127
128    /**
129     * Set whether in 24 hour or AM/PM mode.
130     *
131     * @param is24HourView True = 24 hour mode. False = AM/PM.
132     */
133    public void setIs24HourView(Boolean is24HourView) {
134        mDelegate.setIs24HourView(is24HourView);
135    }
136
137    /**
138     * @return true if this is in 24 hour view else false.
139     */
140    public boolean is24HourView() {
141        return mDelegate.is24HourView();
142    }
143
144    /**
145     * Set the callback that indicates the time has been adjusted by the user.
146     *
147     * @param onTimeChangedListener the callback, should not be null.
148     */
149    public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
150        mDelegate.setOnTimeChangedListener(onTimeChangedListener);
151    }
152
153    /**
154     * Sets the callback that indicates the current time is valid.
155     *
156     * @param callback the callback, may be null
157     * @hide
158     */
159    public void setValidationCallback(@Nullable ValidationCallback callback) {
160        mDelegate.setValidationCallback(callback);
161    }
162
163    @Override
164    public void setEnabled(boolean enabled) {
165        super.setEnabled(enabled);
166        mDelegate.setEnabled(enabled);
167    }
168
169    @Override
170    public boolean isEnabled() {
171        return mDelegate.isEnabled();
172    }
173
174    @Override
175    public int getBaseline() {
176        return mDelegate.getBaseline();
177    }
178
179    @Override
180    protected void onConfigurationChanged(Configuration newConfig) {
181        super.onConfigurationChanged(newConfig);
182        mDelegate.onConfigurationChanged(newConfig);
183    }
184
185    @Override
186    protected Parcelable onSaveInstanceState() {
187        Parcelable superState = super.onSaveInstanceState();
188        return mDelegate.onSaveInstanceState(superState);
189    }
190
191    @Override
192    protected void onRestoreInstanceState(Parcelable state) {
193        BaseSavedState ss = (BaseSavedState) state;
194        super.onRestoreInstanceState(ss.getSuperState());
195        mDelegate.onRestoreInstanceState(ss);
196    }
197
198    @Override
199    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
200        return mDelegate.dispatchPopulateAccessibilityEvent(event);
201    }
202
203    @Override
204    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
205        super.onPopulateAccessibilityEvent(event);
206        mDelegate.onPopulateAccessibilityEvent(event);
207    }
208
209    @Override
210    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
211        super.onInitializeAccessibilityEvent(event);
212        mDelegate.onInitializeAccessibilityEvent(event);
213    }
214
215    @Override
216    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
217        super.onInitializeAccessibilityNodeInfo(info);
218        mDelegate.onInitializeAccessibilityNodeInfo(info);
219    }
220
221    /**
222     * A delegate interface that defined the public API of the TimePicker. Allows different
223     * TimePicker implementations. This would need to be implemented by the TimePicker delegates
224     * for the real behavior.
225     */
226    interface TimePickerDelegate {
227        void setCurrentHour(Integer currentHour);
228        Integer getCurrentHour();
229
230        void setCurrentMinute(Integer currentMinute);
231        Integer getCurrentMinute();
232
233        void setIs24HourView(Boolean is24HourView);
234        boolean is24HourView();
235
236        void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
237        void setValidationCallback(ValidationCallback callback);
238
239        void setEnabled(boolean enabled);
240        boolean isEnabled();
241
242        int getBaseline();
243
244        void onConfigurationChanged(Configuration newConfig);
245
246        Parcelable onSaveInstanceState(Parcelable superState);
247        void onRestoreInstanceState(Parcelable state);
248
249        boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
250        void onPopulateAccessibilityEvent(AccessibilityEvent event);
251        void onInitializeAccessibilityEvent(AccessibilityEvent event);
252        void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
253    }
254
255    /**
256     * A callback interface for updating input validity when the TimePicker
257     * when included into a Dialog.
258     *
259     * @hide
260     */
261    public static interface ValidationCallback {
262        void onValidationChanged(boolean valid);
263    }
264
265    /**
266     * An abstract class which can be used as a start for TimePicker implementations
267     */
268    abstract static class AbstractTimePickerDelegate implements TimePickerDelegate {
269        // The delegator
270        protected TimePicker mDelegator;
271
272        // The context
273        protected Context mContext;
274
275        // The current locale
276        protected Locale mCurrentLocale;
277
278        // Callbacks
279        protected OnTimeChangedListener mOnTimeChangedListener;
280        protected ValidationCallback mValidationCallback;
281
282        public AbstractTimePickerDelegate(TimePicker delegator, Context context) {
283            mDelegator = delegator;
284            mContext = context;
285
286            // initialization based on locale
287            setCurrentLocale(Locale.getDefault());
288        }
289
290        public void setCurrentLocale(Locale locale) {
291            if (locale.equals(mCurrentLocale)) {
292                return;
293            }
294            mCurrentLocale = locale;
295        }
296
297        @Override
298        public void setValidationCallback(ValidationCallback callback) {
299            mValidationCallback = callback;
300        }
301
302        protected void onValidationChanged(boolean valid) {
303            if (mValidationCallback != null) {
304                mValidationCallback.onValidationChanged(valid);
305            }
306        }
307    }
308}
309