19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.Widget; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 21f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganovimport android.content.res.Configuration; 224243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganovimport android.content.res.TypedArray; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 258a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganovimport android.text.format.DateUtils; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 298a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 308a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 31a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganovimport android.view.inputmethod.EditorInfo; 326304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganovimport android.view.inputmethod.InputMethodManager; 33cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganovimport android.widget.NumberPicker.OnValueChangeListener; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganovimport com.android.internal.R; 36a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.text.DateFormatSymbols; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar; 39f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganovimport java.util.Locale; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 424243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * A view for selecting the time of day, in either 24 hour or AM/PM mode. The 434243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * hour, each minute digit, and AM/PM (if applicable) can be conrolled by 444243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * vertical spinners. The hour can be entered by keyboard input. Entering in two 454243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * digit hours can be accomplished by hitting two digits within a timeout of 464243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * about a second (e.g. '1' then '2' to select 12). The minutes can be entered 474243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p' 484243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * or 'P' to pick. For a dialog using this view, see 494243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * {@link android.app.TimePickerDialog}. 504243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov *<p> 514c359b76f9a030f92a302ba74a528faa170bad4eScott Main * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> 524c359b76f9a030f92a302ba74a528faa170bad4eScott Main * guide. 534243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * </p> 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project@Widget 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class TimePicker extends FrameLayout { 57206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 5825f84f323c607bbd9133432fd789ba29b2dcd4d4Svetoslav Ganov private static final boolean DEFAULT_ENABLED_STATE = true; 5925f84f323c607bbd9133432fd789ba29b2dcd4d4Svetoslav Ganov 604243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private static final int HOURS_IN_HALF_DAY = 12; 614243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 634243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * A no-op callback used in the constructor to avoid null checks later in 644243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * the code. 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 704243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // state 724243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private boolean mIs24HourView; 734243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAm; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ui components 77e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private final NumberPicker mHourSpinner; 784243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 79e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private final NumberPicker mMinuteSpinner; 804243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 81e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private final NumberPicker mAmPmSpinner; 824243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 836304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov private final EditText mHourSpinnerInput; 846304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov 856304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov private final EditText mMinuteSpinnerInput; 866304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov 876304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov private final EditText mAmPmSpinnerInput; 886304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov 89206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final TextView mDivider; 90206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 914243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // Note that the legacy implementation of the TimePicker is 924243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // using a button for toggling between AM/PM while the new 934243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // version uses a NumberPicker spinner. Therefore the code 944243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // accommodates these two cases to be backwards compatible. 954243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private final Button mAmPmButton; 964243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 97206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final String[] mAmPmStrings; 98206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 9925f84f323c607bbd9133432fd789ba29b2dcd4d4Svetoslav Ganov private boolean mIsEnabled = DEFAULT_ENABLED_STATE; 10051c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // callbacks 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnTimeChangedListener mOnTimeChangedListener; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1048a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov private Calendar mTempCalendar; 1058a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov 106f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov private Locale mCurrentLocale; 107f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The callback interface used to indicate the time has been adjusted. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnTimeChangedListener { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view The view associated with this listener. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param hourOfDay The current hour. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param minute The current minute. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onTimeChanged(TimePicker view, int hourOfDay, int minute); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public TimePicker(Context context) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1244243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public TimePicker(Context context, AttributeSet attrs) { 1264243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov this(context, attrs, R.attr.timePickerStyle); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public TimePicker(Context context, AttributeSet attrs, int defStyle) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs, defStyle); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 132f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov // initialization based on locale 133f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov setCurrentLocale(Locale.getDefault()); 134f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov 1354243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // process style attributes 1364243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov TypedArray attributesArray = context.obtainStyledAttributes( 1374243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov attrs, R.styleable.TimePicker, defStyle, 0); 1384243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int layoutResourceId = attributesArray.getResourceId( 13953b948d3aec62e886bd10da664a07bdaab916b48Svetoslav Ganov R.styleable.TimePicker_internalLayout, R.layout.time_picker); 1404243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov attributesArray.recycle(); 1414243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 1424243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov LayoutInflater inflater = (LayoutInflater) context.getSystemService( 1434243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov Context.LAYOUT_INFLATER_SERVICE); 1444243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov inflater.inflate(layoutResourceId, this, true); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // hour 147e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner = (NumberPicker) findViewById(R.id.hour); 148cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 149e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { 1506304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov updateInputState(); 1514243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (!is24HourView()) { 152be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) 153be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov || (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) { 1544243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = !mIsAm; 1554243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onTimeChanged(); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 1616304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input); 1626304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1644243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // divider (only for the new widget style) 165206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDivider = (TextView) findViewById(R.id.divider); 1664243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mDivider != null) { 1674243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mDivider.setText(R.string.time_picker_separator); 1684243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 169206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1704243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // minute 171e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); 172e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinuteSpinner.setMinValue(0); 173e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinuteSpinner.setMaxValue(59); 174e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinuteSpinner.setOnLongPressUpdateInterval(100); 175d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); 176cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 177e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { 1786304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov updateInputState(); 1794243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int minValue = mMinuteSpinner.getMinValue(); 1804243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int maxValue = mMinuteSpinner.getMaxValue(); 1814243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (oldVal == maxValue && newVal == minValue) { 182be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov int newHour = mHourSpinner.getValue() + 1; 183be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) { 1844243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = !mIsAm; 1854243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 186206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 187be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov mHourSpinner.setValue(newHour); 1884243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else if (oldVal == minValue && newVal == maxValue) { 189be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov int newHour = mHourSpinner.getValue() - 1; 190be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) { 1914243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = !mIsAm; 1924243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 194be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov mHourSpinner.setValue(newHour); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onTimeChanged(); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 1996304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input); 2006304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); 201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* Get the localized am/pm strings and use them in the spinner */ 203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAmPmStrings = new DateFormatSymbols().getAmPmStrings(); 204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2054243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // am/pm 2064243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov View amPmView = findViewById(R.id.amPm); 2074243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (amPmView instanceof Button) { 2084243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner = null; 2096304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mAmPmSpinnerInput = null; 2104243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton = (Button) amPmView; 2114243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton.setOnClickListener(new OnClickListener() { 2124243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov public void onClick(View button) { 2134243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov button.requestFocus(); 2144243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = !mIsAm; 2154243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 216f821ce7522ad99dc30e59e0266165f5eba79b1e2SeongJae Park onTimeChanged(); 2174243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 2184243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov }); 2194243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 2204243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton = null; 2214243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner = (NumberPicker) amPmView; 2224243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setMinValue(0); 2234243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setMaxValue(1); 2244243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setDisplayedValues(mAmPmStrings); 225cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mAmPmSpinner.setOnValueChangedListener(new OnValueChangeListener() { 2264243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov public void onValueChange(NumberPicker picker, int oldVal, int newVal) { 2276304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov updateInputState(); 2284243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov picker.requestFocus(); 2294243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = !mIsAm; 2304243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 231f821ce7522ad99dc30e59e0266165f5eba79b1e2SeongJae Park onTimeChanged(); 2324243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 2334243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov }); 2346304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input); 2356304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); 2364243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 2374243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 2384243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // update controls to initial state 2394243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateHourControl(); 2404243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setOnTimeChangedListener(NO_OP_CHANGE_LISTENER); 243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2444243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // set to current time 2458a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY)); 2468a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov setCurrentMinute(mTempCalendar.get(Calendar.MINUTE)); 247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isEnabled()) { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setEnabled(false); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2513fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 2523fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // set the content descriptions 2532cdedffcfa5594f9d516fa235d5edf4d4f92c21dSvetoslav Ganov setContentDescriptions(); 2544213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 2554213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov // If not explicitly specified this view is important for accessibility. 2564213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 2574213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 2584213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 26351c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov if (mIsEnabled == enabled) { 26451c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return; 26551c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 267e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinuteSpinner.setEnabled(enabled); 2684243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mDivider != null) { 2694243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mDivider.setEnabled(enabled); 2704243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 271e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setEnabled(enabled); 2724243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mAmPmSpinner != null) { 2734243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setEnabled(enabled); 2744243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 2754243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton.setEnabled(enabled); 2764243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 27751c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov mIsEnabled = enabled; 27851c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 27951c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov 28051c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov @Override 28151c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov public boolean isEnabled() { 28251c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return mIsEnabled; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 285f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov @Override 286f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov protected void onConfigurationChanged(Configuration newConfig) { 287f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov super.onConfigurationChanged(newConfig); 288f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov setCurrentLocale(newConfig.locale); 289f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov } 290f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov 291f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov /** 292f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov * Sets the current locale. 293f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov * 294f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov * @param locale The current locale. 295f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov */ 296f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov private void setCurrentLocale(Locale locale) { 297f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov if (locale.equals(mCurrentLocale)) { 298f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov return; 299f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov } 300f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov mCurrentLocale = locale; 301f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov mTempCalendar = Calendar.getInstance(locale); 302f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov } 303f5926962cc665d4a2e6464f9ba9e3e9788496a6fSvetoslav Ganov 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Used to save / restore state of time picker 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class SavedState extends BaseSavedState { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mHour; 3104243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mMinute; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcelable superState, int hour, int minute) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHour = hour; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinute = minute; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3184243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHour = in.readInt(); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinute = in.readInt(); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getHour() { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHour; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMinute() { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMinute; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel dest, int flags) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(dest, flags); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.writeInt(mHour); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.writeInt(mMinute); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3406304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov @SuppressWarnings({"unused", "hiding"}) 3414243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Parcelable onSaveInstanceState() { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 3554243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return new SavedState(superState, getCurrentHour(), getCurrentMinute()); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onRestoreInstanceState(Parcelable state) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCurrentHour(ss.getHour()); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCurrentMinute(ss.getMinute()); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the callback that indicates the time has been adjusted by the user. 3684243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param onTimeChangedListener the callback, should not be null. 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnTimeChangedListener = onTimeChangedListener; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3764243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * @return The current hour in the range (0-23). 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Integer getCurrentHour() { 3794243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int currentHour = mHourSpinner.getValue(); 380be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if (is24HourView()) { 3814243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return currentHour; 382be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov } else if (mIsAm) { 383be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov return currentHour % HOURS_IN_HALF_DAY; 3844243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 385be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; 3864243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current hour. 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCurrentHour(Integer currentHour) { 3934243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // why was Integer used in the first place? 3944243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (currentHour == null || currentHour == getCurrentHour()) { 3954243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return; 3964243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 3974243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (!is24HourView()) { 3984243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // convert [0,23] ordinal to wall clock display 399be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if (currentHour >= HOURS_IN_HALF_DAY) { 4004243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIsAm = false; 401be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov if (currentHour > HOURS_IN_HALF_DAY) { 402be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov currentHour = currentHour - HOURS_IN_HALF_DAY; 403be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov } 4044243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 405be17a7f269479ed91b6fe8a80966d4605c805a0aSvetoslav Ganov mIsAm = true; 4064243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (currentHour == 0) { 4074243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov currentHour = HOURS_IN_HALF_DAY; 4084243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 4094243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 4104243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 4114243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 4124243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mHourSpinner.setValue(currentHour); 4134243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov onTimeChanged(); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set whether in 24 hour or AM/PM mode. 4184243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param is24HourView True = 24 hour mode. False = AM/PM. 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setIs24HourView(Boolean is24HourView) { 4224243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mIs24HourView == is24HourView) { 4234243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4254243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mIs24HourView = is24HourView; 4264243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // cache the current hour since spinner range changes 4274243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int currentHour = getCurrentHour(); 4284243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateHourControl(); 4294243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov // set value after spinner range is updated 4304243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov setCurrentHour(currentHour); 4314243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov updateAmPmControl(); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if this is in 24 hour view else false. 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean is24HourView() { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mIs24HourView; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4404243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The current minute. 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Integer getCurrentMinute() { 4454243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return mMinuteSpinner.getValue(); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the current minute (0-59). 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCurrentMinute(Integer currentMinute) { 4524243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (currentMinute == getCurrentMinute()) { 4534243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov return; 4544243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 4554243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mMinuteSpinner.setValue(currentMinute); 4564243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov onTimeChanged(); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getBaseline() { 461e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mHourSpinner.getBaseline(); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4648a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov @Override 4653fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 4663fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov onPopulateAccessibilityEvent(event); 4673fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov return true; 4683fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov } 4693fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 4703fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov @Override 471736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 472736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov super.onPopulateAccessibilityEvent(event); 473736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 4748a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov int flags = DateUtils.FORMAT_SHOW_TIME; 4758a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov if (mIs24HourView) { 4768a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov flags |= DateUtils.FORMAT_24HOUR; 4778a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov } else { 4788a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov flags |= DateUtils.FORMAT_12HOUR; 4798a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov } 4808a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour()); 4818a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov mTempCalendar.set(Calendar.MINUTE, getCurrentMinute()); 4828a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov String selectedDateUtterance = DateUtils.formatDateTime(mContext, 4838a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov mTempCalendar.getTimeInMillis(), flags); 4848a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov event.getText().add(selectedDateUtterance); 4858a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov } 4868a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov 4878a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 4888a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 4898a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 4908a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(TimePicker.class.getName()); 4918a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 4928a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 4938a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 4948a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 4958a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 4968a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(TimePicker.class.getName()); 4978a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 4988a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 4994243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private void updateHourControl() { 5004243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (is24HourView()) { 501e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setMinValue(0); 502e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setMaxValue(23); 503d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 505e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setMinValue(1); 506e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setMaxValue(12); 507e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mHourSpinner.setFormatter(null); 5084243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 5094243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 5104243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 5114243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private void updateAmPmControl() { 5124243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (is24HourView()) { 5134243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mAmPmSpinner != null) { 5144243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setVisibility(View.GONE); 5154243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 5164243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton.setVisibility(View.GONE); 5174243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 5184243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 5194243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov int index = mIsAm ? Calendar.AM : Calendar.PM; 5204243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (mAmPmSpinner != null) { 5214243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setValue(index); 5224243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmSpinner.setVisibility(View.VISIBLE); 5234243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } else { 5244243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton.setText(mAmPmStrings[index]); 5254243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mAmPmButton.setVisibility(View.VISIBLE); 5264243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5288a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void onTimeChanged() { 5328a2a89588c3889b999a8fffa2d7c7a5c3ce25eb8Svetoslav Ganov sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mOnTimeChangedListener != null) { 534206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute()); 535206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5373fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 5383fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov private void setContentDescriptions() { 5393fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // Minute 540d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mMinuteSpinner, R.id.increment, 541d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_increment_minute_button); 542d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mMinuteSpinner, R.id.decrement, 543d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_decrement_minute_button); 5443fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // Hour 545d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mHourSpinner, R.id.increment, 546d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_increment_hour_button); 547d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mHourSpinner, R.id.decrement, 548d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_decrement_hour_button); 5493fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // AM/PM 55011c91328185c017e65930f137e69191ddef7e111Svetoslav Ganov if (mAmPmSpinner != null) { 551d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mAmPmSpinner, R.id.increment, 552d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_increment_set_pm_button); 553d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov trySetContentDescription(mAmPmSpinner, R.id.decrement, 554d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.string.time_picker_decrement_set_am_button); 555d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 556d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 557d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 558d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void trySetContentDescription(View root, int viewId, int contDescResId) { 559d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov View target = root.findViewById(viewId); 560d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (target != null) { 561d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov target.setContentDescription(mContext.getString(contDescResId)); 56211c91328185c017e65930f137e69191ddef7e111Svetoslav Ganov } 5633fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov } 5646304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov 5656304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov private void updateInputState() { 5666304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov // Make sure that if the user changes the value and the IME is active 5676304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov // for one of the inputs if this widget, the IME is closed. If the user 5686304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov // changed the value via the IME and there is a next input the IME will 5696304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov // be shown, otherwise the user chose another means of changing the 5706304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov // value and having the IME up makes no sense. 5716304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); 5726304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov if (inputMethodManager != null) { 5736304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov if (inputMethodManager.isActive(mHourSpinnerInput)) { 5746304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mHourSpinnerInput.clearFocus(); 5756304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 5766304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) { 5776304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mMinuteSpinnerInput.clearFocus(); 5786304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 5796304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) { 5806304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mAmPmSpinnerInput.clearFocus(); 5816304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 5826304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } 5836304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } 5846304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 586