1eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio/* 2eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Copyright (C) 2013 The Android Open Source Project 3eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 4eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * you may not use this file except in compliance with the License. 6eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * You may obtain a copy of the License at 7eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 8eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 10eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * See the License for the specific language governing permissions and 14eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * limitations under the License. 15eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 16eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 17eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Megliopackage android.widget; 18eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 19eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.Context; 20eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.TypedArray; 21eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.os.Parcelable; 22eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.text.format.DateFormat; 23014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglioimport android.text.format.DateUtils; 24eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.util.AttributeSet; 25eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.LayoutInflater; 26eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.View; 27eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.ViewGroup; 28eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.accessibility.AccessibilityEvent; 29daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteimport android.view.inputmethod.EditorInfo; 30daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteimport android.view.inputmethod.InputMethodManager; 31eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport com.android.internal.R; 32eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 33eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.Calendar; 34eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 35daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteimport libcore.icu.LocaleData; 36eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 37daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteimport static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; 38daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteimport static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES; 39eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 40daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette/** 41daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * A delegate implementing the basic spinner-based TimePicker. 42daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette */ 43daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viveretteclass TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { 44eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final boolean DEFAULT_ENABLED_STATE = true; 45eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int HOURS_IN_HALF_DAY = 12; 46eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 47daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final NumberPicker mHourSpinner; 48daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final NumberPicker mMinuteSpinner; 49daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final NumberPicker mAmPmSpinner; 50daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final EditText mHourSpinnerInput; 51daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final EditText mMinuteSpinnerInput; 52daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final EditText mAmPmSpinnerInput; 53daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final TextView mDivider; 54eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 55daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Note that the legacy implementation of the TimePicker is 56daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // using a button for toggling between AM/PM while the new 57daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // version uses a NumberPicker spinner. Therefore the code 58daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // accommodates these two cases to be backwards compatible. 59daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final Button mAmPmButton; 60eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 61daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private final String[] mAmPmStrings; 6226c563b051aacf5be66a0453be00a645ed3f50cdAlan Viverette 6368016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette private final Calendar mTempCalendar; 6468016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette 65daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private boolean mIsEnabled = DEFAULT_ENABLED_STATE; 66daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private boolean mHourWithTwoDigit; 67daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private char mHourFormat; 68014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio 6968016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette private boolean mIs24HourView; 7068016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette private boolean mIsAm; 7168016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette 723053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase public TimePickerSpinnerDelegate(TimePicker delegator, Context context, AttributeSet attrs, 733053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase int defStyleAttr, int defStyleRes) { 74eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super(delegator, context); 75eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 76eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // process style attributes 77daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final TypedArray a = mContext.obtainStyledAttributes( 78daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); 79daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final int layoutResourceId = a.getResourceId( 80daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy); 8160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette a.recycle(); 825134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 83daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final LayoutInflater inflater = LayoutInflater.from(mContext); 84daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette inflater.inflate(layoutResourceId, mDelegator, true); 85daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 86daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // hour 87daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour); 88daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 89daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { 90daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateInputState(); 914420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (!is24Hour()) { 92daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) || 93daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) { 94daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = !mIsAm; 95daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 96daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 97daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 98daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette onTimeChanged(); 99daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 100daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette }); 101daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input); 102daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); 103daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 104daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // divider (only for the new widget style) 105daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDivider = (TextView) mDelegator.findViewById(R.id.divider); 106daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mDivider != null) { 107daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette setDividerText(); 108daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 109daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 110daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // minute 111daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute); 112daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setMinValue(0); 113daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setMaxValue(59); 114daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setOnLongPressUpdateInterval(100); 115daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); 116daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 117daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { 118daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateInputState(); 119daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int minValue = mMinuteSpinner.getMinValue(); 120daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int maxValue = mMinuteSpinner.getMaxValue(); 121daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (oldVal == maxValue && newVal == minValue) { 122daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int newHour = mHourSpinner.getValue() + 1; 1234420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (!is24Hour() && newHour == HOURS_IN_HALF_DAY) { 124daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = !mIsAm; 125daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 126daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 127daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setValue(newHour); 128daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else if (oldVal == minValue && newVal == maxValue) { 129daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int newHour = mHourSpinner.getValue() - 1; 1304420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (!is24Hour() && newHour == HOURS_IN_HALF_DAY - 1) { 131daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = !mIsAm; 132daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 133daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 134daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setValue(newHour); 135daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 136daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette onTimeChanged(); 137daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 138daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette }); 139daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input); 140daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); 141daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 142daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Get the localized am/pm strings and use them in the spinner. 143daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmStrings = getAmPmStrings(context); 144daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 145daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // am/pm 146daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final View amPmView = mDelegator.findViewById(R.id.amPm); 147daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (amPmView instanceof Button) { 148daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner = null; 149daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinnerInput = null; 150daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton = (Button) amPmView; 151daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton.setOnClickListener(new View.OnClickListener() { 152daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public void onClick(View button) { 153daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette button.requestFocus(); 154daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = !mIsAm; 155daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 156daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette onTimeChanged(); 157daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 158daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette }); 159daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 160daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton = null; 161daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner = (NumberPicker) amPmView; 162daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setMinValue(0); 163daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setMaxValue(1); 164daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setDisplayedValues(mAmPmStrings); 165daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { 166daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public void onValueChange(NumberPicker picker, int oldVal, int newVal) { 167daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateInputState(); 168daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette picker.requestFocus(); 169daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = !mIsAm; 170daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 171daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette onTimeChanged(); 172daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 173daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette }); 174daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input); 175daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); 176daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 177daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 178daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (isAmPmAtStart()) { 179daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Move the am/pm view to the beginning 180daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout); 181daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette amPmParent.removeView(amPmView); 182daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette amPmParent.addView(amPmView, 0); 183daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme 184daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // for example and not for Holo Theme) 185daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette ViewGroup.MarginLayoutParams lp = 186daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams(); 187daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final int startMargin = lp.getMarginStart(); 188daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final int endMargin = lp.getMarginEnd(); 189daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (startMargin != endMargin) { 190daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette lp.setMarginStart(endMargin); 191daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette lp.setMarginEnd(startMargin); 192daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 193daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 19467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 195daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette getHourFormatData(); 196eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 197daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // update controls to initial state 198daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateHourControl(); 199daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateMinuteControl(); 200daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 201eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 202daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // set to current time 20368016a66f6d981676b193e8f52a06bee785c8da9Alan Viverette mTempCalendar = Calendar.getInstance(mLocale); 2044420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette setHour(mTempCalendar.get(Calendar.HOUR_OF_DAY)); 2054420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette setMinute(mTempCalendar.get(Calendar.MINUTE)); 206eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 207daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (!isEnabled()) { 208daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette setEnabled(false); 209daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 210eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 211daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // set the content descriptions 212daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette setContentDescriptions(); 213eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 214daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // If not explicitly specified this view is important for accessibility. 215daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 216daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 217daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 218eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 219eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 220daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void getHourFormatData() { 2214420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale, 222daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette (mIs24HourView) ? "Hm" : "hm"); 223daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final int lengthPattern = bestDateTimePattern.length(); 224daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourWithTwoDigit = false; 225daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette char hourFormat = '\0'; 226daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save 227daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // the hour format that we found. 228daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette for (int i = 0; i < lengthPattern; i++) { 229daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final char c = bestDateTimePattern.charAt(i); 230daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { 231daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourFormat = c; 232daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { 233daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourWithTwoDigit = true; 234daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 235daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette break; 236daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 237daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 238eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 239eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 240daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private boolean isAmPmAtStart() { 2414420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale, 242daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette "hm" /* skeleton */); 243eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 244daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return bestDateTimePattern.startsWith("a"); 245eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 246eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 247daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette /** 248daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". 249daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * 250daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * See http://unicode.org/cldr/trac/browser/trunk/common/main 251daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * 252daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the 253daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette * separator as the character which is just after the hour marker in the returned pattern. 254daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette */ 255daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void setDividerText() { 256daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final String skeleton = (mIs24HourView) ? "Hm" : "hm"; 2574420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale, 258daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette skeleton); 259daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette final String separatorText; 260daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int hourIndex = bestDateTimePattern.lastIndexOf('H'); 261daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (hourIndex == -1) { 262daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette hourIndex = bestDateTimePattern.lastIndexOf('h'); 263eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 264daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (hourIndex == -1) { 265daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Default case 266daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette separatorText = ":"; 267eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 268daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1); 269daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (minuteIndex == -1) { 270daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1)); 271eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 272daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex); 273eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 274eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 275daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDivider.setText(separatorText); 276eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 277eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 278eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 2794420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public void setHour(int hour) { 2804420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette setCurrentHour(hour, true); 281daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 282daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 283646a0f8e0d0a9f94a5969d09a498f5de5fe40a88Alan Viverette private void setCurrentHour(int currentHour, boolean notifyTimeChanged) { 284daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // why was Integer used in the first place? 2854420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (currentHour == getHour()) { 286eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 287eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 2884420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (!is24Hour()) { 289daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // convert [0,23] ordinal to wall clock display 290daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (currentHour >= HOURS_IN_HALF_DAY) { 291daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = false; 292daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (currentHour > HOURS_IN_HALF_DAY) { 293daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette currentHour = currentHour - HOURS_IN_HALF_DAY; 294daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 295daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 296daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mIsAm = true; 297daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (currentHour == 0) { 298daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette currentHour = HOURS_IN_HALF_DAY; 299daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 300daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 301daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 302daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 303daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setValue(currentHour); 304daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (notifyTimeChanged) { 305daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette onTimeChanged(); 306daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 307eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 308eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 309eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 3104420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public int getHour() { 311daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int currentHour = mHourSpinner.getValue(); 3124420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (is24Hour()) { 313eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return currentHour; 314daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else if (mIsAm) { 315daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return currentHour % HOURS_IN_HALF_DAY; 316eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 317daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; 318eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 319eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 320eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 321eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 3224420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public void setMinute(int minute) { 3234420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (minute == getMinute()) { 324eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 325eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 3264420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette mMinuteSpinner.setValue(minute); 327eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio onTimeChanged(); 328eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 329eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 330eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 3314420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public int getMinute() { 332daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return mMinuteSpinner.getValue(); 333eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 334eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 3354420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public void setIs24Hour(boolean is24Hour) { 3364420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (mIs24HourView == is24Hour) { 337eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 338eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 339daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!! 3404420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette int currentHour = getHour(); 341daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Order is important here. 3424420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette mIs24HourView = is24Hour; 343daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette getHourFormatData(); 344daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateHourControl(); 345daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // set value after spinner range is updated 346daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette setCurrentHour(currentHour, false); 347daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateMinuteControl(); 348daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette updateAmPmControl(); 349eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 350eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 351eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 3524420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette public boolean is24Hour() { 353eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mIs24HourView; 354eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 355eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 356eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 357daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTimeChangedListener) { 358daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mOnTimeChangedListener = onTimeChangedListener; 359eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 360eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 361eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 362eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setEnabled(boolean enabled) { 363daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinner.setEnabled(enabled); 364daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mDivider != null) { 365daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDivider.setEnabled(enabled); 366daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 367daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setEnabled(enabled); 368daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mAmPmSpinner != null) { 369daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setEnabled(enabled); 370daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 371daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton.setEnabled(enabled); 372daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 373eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsEnabled = enabled; 374eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 375eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 376eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 377eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean isEnabled() { 378eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mIsEnabled; 379eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 380eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 381eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 382eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getBaseline() { 383daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return mHourSpinner.getBaseline(); 384eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 385eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 386eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 387eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Parcelable onSaveInstanceState(Parcelable superState) { 3886b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette return new SavedState(superState, getHour(), getMinute(), is24Hour()); 389eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 390eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 391eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 392eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onRestoreInstanceState(Parcelable state) { 3936b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (state instanceof SavedState) { 3946b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final SavedState ss = (SavedState) state; 3956b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette setHour(ss.getHour()); 3966b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette setMinute(ss.getMinute()); 3976b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette } 398014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } 399014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio 400014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio @Override 401eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 402014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio onPopulateAccessibilityEvent(event); 403014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio return true; 404eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 405eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 406eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 407eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 408014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio int flags = DateUtils.FORMAT_SHOW_TIME; 409014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio if (mIs24HourView) { 410014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio flags |= DateUtils.FORMAT_24HOUR; 411014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } else { 412014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio flags |= DateUtils.FORMAT_12HOUR; 413014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } 4144420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette mTempCalendar.set(Calendar.HOUR_OF_DAY, getHour()); 4154420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette mTempCalendar.set(Calendar.MINUTE, getMinute()); 416daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette String selectedDateUtterance = DateUtils.formatDateTime(mContext, 417014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio mTempCalendar.getTimeInMillis(), flags); 418daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette event.getText().add(selectedDateUtterance); 419eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 420eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 421daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void updateInputState() { 422daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Make sure that if the user changes the value and the IME is active 423daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // for one of the inputs if this widget, the IME is closed. If the user 424daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // changed the value via the IME and there is a next input the IME will 425daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // be shown, otherwise the user chose another means of changing the 426daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // value and having the IME up makes no sense. 427daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); 428daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (inputMethodManager != null) { 429daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (inputMethodManager.isActive(mHourSpinnerInput)) { 430daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinnerInput.clearFocus(); 431daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); 432daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) { 433daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinnerInput.clearFocus(); 434daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); 435daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) { 436daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinnerInput.clearFocus(); 437daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); 438daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 439daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 440daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 441daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 442daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void updateAmPmControl() { 4434420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (is24Hour()) { 444daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mAmPmSpinner != null) { 445daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setVisibility(View.GONE); 446daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 447daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton.setVisibility(View.GONE); 448daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 449daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 450daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette int index = mIsAm ? Calendar.AM : Calendar.PM; 451daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mAmPmSpinner != null) { 452daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setValue(index); 453daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmSpinner.setVisibility(View.VISIBLE); 454daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 455daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton.setText(mAmPmStrings[index]); 456daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mAmPmButton.setVisibility(View.VISIBLE); 457daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 458daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 459daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 460daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 461daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette 462daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void onTimeChanged() { 463daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 464daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mOnTimeChangedListener != null) { 4654420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), 4664420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette getMinute()); 467daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 468eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 469eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 470daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void updateHourControl() { 4714420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (is24Hour()) { 472daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // 'k' means 1-24 hour 473daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mHourFormat == 'k') { 474daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMinValue(1); 475daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMaxValue(24); 476daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 477daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMinValue(0); 478daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMaxValue(23); 479daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 480daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 481daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // 'K' means 0-11 hour 482daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mHourFormat == 'K') { 483daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMinValue(0); 484daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMaxValue(11); 485daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 486daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMinValue(1); 487daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setMaxValue(12); 488daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 489daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 490daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null); 491eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 492eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 493daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void updateMinuteControl() { 4944420ae875de711a91dc10f7f4dd5a9cc62221ac8Alan Viverette if (is24Hour()) { 495daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); 496daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } else { 497daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); 498daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 499eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 500eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 501daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void setContentDescriptions() { 502daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Minute 503daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mMinuteSpinner, R.id.increment, 504daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_increment_minute_button); 505daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mMinuteSpinner, R.id.decrement, 506daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_decrement_minute_button); 507daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // Hour 508daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mHourSpinner, R.id.increment, 509daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_increment_hour_button); 510daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mHourSpinner, R.id.decrement, 511daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_decrement_hour_button); 512daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette // AM/PM 513daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (mAmPmSpinner != null) { 514daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mAmPmSpinner, R.id.increment, 515daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_increment_set_pm_button); 516daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette trySetContentDescription(mAmPmSpinner, R.id.decrement, 517daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette R.string.time_picker_decrement_set_am_button); 518daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette } 519eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 520eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 521daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette private void trySetContentDescription(View root, int viewId, int contDescResId) { 522daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette View target = root.findViewById(viewId); 523daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette if (target != null) { 524daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette target.setContentDescription(mContext.getString(contDescResId)); 525eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 526eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 527eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 528daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette public static String[] getAmPmStrings(Context context) { 529daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette String[] result = new String[2]; 530daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); 53114b503947727d7e58c9f2d50ceada378031fbe59Narayan Kamath result[0] = d.amPm[0].length() > 4 ? d.narrowAm : d.amPm[0]; 53214b503947727d7e58c9f2d50ceada378031fbe59Narayan Kamath result[1] = d.amPm[1].length() > 4 ? d.narrowPm : d.amPm[1]; 533daf33ed85353ab7d7a7668dd0e3f9a66f0d5583fAlan Viverette return result; 534eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 535eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio} 536