TimePickerClockDelegatepublic class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements RadialTimePickerView.OnValueSelectedListenerA delegate implementing the radial clock-based TimePicker. |
Fields Summary |
---|
private static final String | TAG | private static final int | HOUR_INDEX | private static final int | MINUTE_INDEX | private static final int | AMPM_INDEX | private static final int | ENABLE_PICKER_INDEX | static final int | AM | static final int | PM | private static final boolean | DEFAULT_ENABLED_STATE | private boolean | mIsEnabled | private static final int | HOURS_IN_HALF_DAY | private final android.view.View | mHeaderView | private final TextView | mHourView | private final TextView | mMinuteView | private final android.view.View | mAmPmLayout | private final CheckedTextView | mAmLabel | private final CheckedTextView | mPmLabel | private final RadialTimePickerView | mRadialTimePickerView | private final TextView | mSeparatorView | private final String | mAmText | private final String | mPmText | private final float | mDisabledAlpha | private boolean | mAllowAutoAdvance | private int | mInitialHourOfDay | private int | mInitialMinute | private boolean | mIs24HourView | private char | mPlaceholderText | private String | mDoublePlaceholderText | private String | mDeletedKeyFormat | private boolean | mInKbMode | private ArrayList | mTypedTimes | private Node | mLegalTimesTree | private int | mAmKeyCode | private int | mPmKeyCode | private String | mSelectHours | private String | mSelectMinutes | private CharSequence | mLastAnnouncedText | private boolean | mLastAnnouncedIsHour | private Calendar | mTempCalendar | private final View.OnClickListener | mClickListener | private final View.OnKeyListener | mKeyListener | private final View.OnFocusChangeListener | mFocusListener |
Constructors Summary |
---|
public TimePickerClockDelegate(TimePicker delegator, android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)
super(delegator, context);
// process style attributes
final TypedArray a = mContext.obtainStyledAttributes(attrs,
R.styleable.TimePicker, defStyleAttr, defStyleRes);
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
final Resources res = mContext.getResources();
mSelectHours = res.getString(R.string.select_hours);
mSelectMinutes = res.getString(R.string.select_minutes);
String[] amPmStrings = TimePickerSpinnerDelegate.getAmPmStrings(context);
mAmText = amPmStrings[0];
mPmText = amPmStrings[1];
final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
R.layout.time_picker_holo);
final View mainView = inflater.inflate(layoutResourceId, delegator);
mHeaderView = mainView.findViewById(R.id.time_header);
mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
// Set up hour/minute labels.
mHourView = (TextView) mHeaderView.findViewById(R.id.hours);
mHourView.setOnClickListener(mClickListener);
mHourView.setAccessibilityDelegate(
new ClickActionDelegate(context, R.string.select_hours));
mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator);
mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes);
mMinuteView.setOnClickListener(mClickListener);
mMinuteView.setAccessibilityDelegate(
new ClickActionDelegate(context, R.string.select_minutes));
final int headerTimeTextAppearance = a.getResourceId(
R.styleable.TimePicker_headerTimeTextAppearance, 0);
if (headerTimeTextAppearance != 0) {
mHourView.setTextAppearance(context, headerTimeTextAppearance);
mSeparatorView.setTextAppearance(context, headerTimeTextAppearance);
mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
}
// Now that we have text appearances out of the way, make sure the hour
// and minute views are correctly sized.
mHourView.setMinWidth(computeStableWidth(mHourView, 24));
mMinuteView.setMinWidth(computeStableWidth(mMinuteView, 60));
// TODO: This can be removed once we support themed color state lists.
final int headerSelectedTextColor = a.getColor(
R.styleable.TimePicker_headerSelectedTextColor,
res.getColor(R.color.timepicker_default_selector_color_material));
mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(),
R.attr.state_selected, headerSelectedTextColor));
mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(),
R.attr.state_selected, headerSelectedTextColor));
// Set up AM/PM labels.
mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout);
mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
mAmLabel.setText(amPmStrings[0]);
mAmLabel.setOnClickListener(mClickListener);
mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
mPmLabel.setText(amPmStrings[1]);
mPmLabel.setOnClickListener(mClickListener);
final int headerAmPmTextAppearance = a.getResourceId(
R.styleable.TimePicker_headerAmPmTextAppearance, 0);
if (headerAmPmTextAppearance != 0) {
mAmLabel.setTextAppearance(context, headerAmPmTextAppearance);
mPmLabel.setTextAppearance(context, headerAmPmTextAppearance);
}
a.recycle();
// Pull disabled alpha from theme.
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
mDisabledAlpha = outValue.getFloat();
mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
R.id.radial_picker);
setupListeners();
mAllowAutoAdvance = true;
// Set up for keyboard mode.
mDoublePlaceholderText = res.getString(R.string.time_placeholder);
mDeletedKeyFormat = res.getString(R.string.deleted_key);
mPlaceholderText = mDoublePlaceholderText.charAt(0);
mAmKeyCode = mPmKeyCode = -1;
generateLegalTimesTree();
// Initialize with current time
final Calendar calendar = Calendar.getInstance(mCurrentLocale);
final int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
final int currentMinute = calendar.get(Calendar.MINUTE);
initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
|
Methods Summary |
---|
private boolean | addKeyIfLegal(int keyCode)
// If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
// we'll need to see if AM/PM have been typed.
if ((mIs24HourView && mTypedTimes.size() == 4) ||
(!mIs24HourView && isTypedTimeFullyLegal())) {
return false;
}
mTypedTimes.add(keyCode);
if (!isTypedTimeLegalSoFar()) {
deleteLastTypedKey();
return false;
}
int val = getValFromKeyCode(keyCode);
mDelegator.announceForAccessibility(String.format("%d", val));
// Automatically fill in 0's if AM or PM was legally entered.
if (isTypedTimeFullyLegal()) {
if (!mIs24HourView && mTypedTimes.size() <= 3) {
mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
}
onValidationChanged(true);
}
return true;
| private int | computeStableWidth(TextView v, int maxNumber)
int maxWidth = 0;
for (int i = 0; i < maxNumber; i++) {
final String text = String.format("%02d", i);
v.setText(text);
v.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final int width = v.getMeasuredWidth();
if (width > maxWidth) {
maxWidth = width;
}
}
return maxWidth;
| private int | deleteLastTypedKey()
int deleted = mTypedTimes.remove(mTypedTimes.size() - 1);
if (!isTypedTimeFullyLegal()) {
onValidationChanged(false);
}
return deleted;
| public boolean | dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
onPopulateAccessibilityEvent(event);
return true;
| private void | finishKbMode()Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
mInKbMode = false;
if (!mTypedTimes.isEmpty()) {
int values[] = getEnteredTime(null);
mRadialTimePickerView.setCurrentHour(values[0]);
mRadialTimePickerView.setCurrentMinute(values[1]);
if (!mIs24HourView) {
mRadialTimePickerView.setAmOrPm(values[2]);
}
mTypedTimes.clear();
}
updateDisplay(false);
mRadialTimePickerView.setInputEnabled(true);
| private void | generateLegalTimesTree()Create a tree for deciding what keys can legally be typed.
// Create a quick cache of numbers to their keycodes.
final int k0 = KeyEvent.KEYCODE_0;
final int k1 = KeyEvent.KEYCODE_1;
final int k2 = KeyEvent.KEYCODE_2;
final int k3 = KeyEvent.KEYCODE_3;
final int k4 = KeyEvent.KEYCODE_4;
final int k5 = KeyEvent.KEYCODE_5;
final int k6 = KeyEvent.KEYCODE_6;
final int k7 = KeyEvent.KEYCODE_7;
final int k8 = KeyEvent.KEYCODE_8;
final int k9 = KeyEvent.KEYCODE_9;
// The root of the tree doesn't contain any numbers.
mLegalTimesTree = new Node();
if (mIs24HourView) {
// We'll be re-using these nodes, so we'll save them.
Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5);
Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
// The first digit must be followed by the second digit.
minuteFirstDigit.addChild(minuteSecondDigit);
// The first digit may be 0-1.
Node firstDigit = new Node(k0, k1);
mLegalTimesTree.addChild(firstDigit);
// When the first digit is 0-1, the second digit may be 0-5.
Node secondDigit = new Node(k0, k1, k2, k3, k4, k5);
firstDigit.addChild(secondDigit);
// We may now be followed by the first minute digit. E.g. 00:09, 15:58.
secondDigit.addChild(minuteFirstDigit);
// When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9.
Node thirdDigit = new Node(k6, k7, k8, k9);
// The time must now be finished. E.g. 0:55, 1:08.
secondDigit.addChild(thirdDigit);
// When the first digit is 0-1, the second digit may be 6-9.
secondDigit = new Node(k6, k7, k8, k9);
firstDigit.addChild(secondDigit);
// We must now be followed by the first minute digit. E.g. 06:50, 18:20.
secondDigit.addChild(minuteFirstDigit);
// The first digit may be 2.
firstDigit = new Node(k2);
mLegalTimesTree.addChild(firstDigit);
// When the first digit is 2, the second digit may be 0-3.
secondDigit = new Node(k0, k1, k2, k3);
firstDigit.addChild(secondDigit);
// We must now be followed by the first minute digit. E.g. 20:50, 23:09.
secondDigit.addChild(minuteFirstDigit);
// When the first digit is 2, the second digit may be 4-5.
secondDigit = new Node(k4, k5);
firstDigit.addChild(secondDigit);
// We must now be followd by the last minute digit. E.g. 2:40, 2:53.
secondDigit.addChild(minuteSecondDigit);
// The first digit may be 3-9.
firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9);
mLegalTimesTree.addChild(firstDigit);
// We must now be followed by the first minute digit. E.g. 3:57, 8:12.
firstDigit.addChild(minuteFirstDigit);
} else {
// We'll need to use the AM/PM node a lot.
// Set up AM and PM to respond to "a" and "p".
Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM));
// The first hour digit may be 1.
Node firstDigit = new Node(k1);
mLegalTimesTree.addChild(firstDigit);
// We'll allow quick input of on-the-hour times. E.g. 1pm.
firstDigit.addChild(ampm);
// When the first digit is 1, the second digit may be 0-2.
Node secondDigit = new Node(k0, k1, k2);
firstDigit.addChild(secondDigit);
// Also for quick input of on-the-hour times. E.g. 10pm, 12am.
secondDigit.addChild(ampm);
// When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5.
Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5);
secondDigit.addChild(thirdDigit);
// The time may be finished now. E.g. 1:02pm, 1:25am.
thirdDigit.addChild(ampm);
// When the first digit is 1, the second digit is 0-2, and the third digit is 0-5,
// the fourth digit may be 0-9.
Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
thirdDigit.addChild(fourthDigit);
// The time must be finished now. E.g. 10:49am, 12:40pm.
fourthDigit.addChild(ampm);
// When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9.
thirdDigit = new Node(k6, k7, k8, k9);
secondDigit.addChild(thirdDigit);
// The time must be finished now. E.g. 1:08am, 1:26pm.
thirdDigit.addChild(ampm);
// When the first digit is 1, the second digit may be 3-5.
secondDigit = new Node(k3, k4, k5);
firstDigit.addChild(secondDigit);
// When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9.
thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
secondDigit.addChild(thirdDigit);
// The time must be finished now. E.g. 1:39am, 1:50pm.
thirdDigit.addChild(ampm);
// The hour digit may be 2-9.
firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9);
mLegalTimesTree.addChild(firstDigit);
// We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm.
firstDigit.addChild(ampm);
// When the first digit is 2-9, the second digit may be 0-5.
secondDigit = new Node(k0, k1, k2, k3, k4, k5);
firstDigit.addChild(secondDigit);
// When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9.
thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
secondDigit.addChild(thirdDigit);
// The time must be finished now. E.g. 2:57am, 9:30pm.
thirdDigit.addChild(ampm);
}
| private int | getAmOrPmKeyCode(int amOrPm)Get the keycode value for AM and PM in the current language.
// Cache the codes.
if (mAmKeyCode == -1 || mPmKeyCode == -1) {
// Find the first character in the AM/PM text that is unique.
final KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
final CharSequence amText = mAmText.toLowerCase(mCurrentLocale);
final CharSequence pmText = mPmText.toLowerCase(mCurrentLocale);
final int N = Math.min(amText.length(), pmText.length());
for (int i = 0; i < N; i++) {
final char amChar = amText.charAt(i);
final char pmChar = pmText.charAt(i);
if (amChar != pmChar) {
// There should be 4 events: a down and up for both AM and PM.
final KeyEvent[] events = kcm.getEvents(new char[] { amChar, pmChar });
if (events != null && events.length == 4) {
mAmKeyCode = events[0].getKeyCode();
mPmKeyCode = events[2].getKeyCode();
} else {
Log.e(TAG, "Unable to find keycodes for AM and PM.");
}
break;
}
}
}
if (amOrPm == AM) {
return mAmKeyCode;
} else if (amOrPm == PM) {
return mPmKeyCode;
}
return -1;
| public int | getBaseline()
// does not support baseline alignment
return -1;
| public java.lang.Integer | getCurrentHour()
int currentHour = mRadialTimePickerView.getCurrentHour();
if (mIs24HourView) {
return currentHour;
} else {
switch(mRadialTimePickerView.getAmOrPm()) {
case PM:
return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
case AM:
default:
return currentHour % HOURS_IN_HALF_DAY;
}
}
| private int | getCurrentItemShowing()
return mRadialTimePickerView.getCurrentItemShowing();
| public java.lang.Integer | getCurrentMinute()
return mRadialTimePickerView.getCurrentMinute();
| private int[] | getEnteredTime(boolean[] enteredZeros)Get the currently-entered time, as integer values of the hours and minutes typed.
int amOrPm = -1;
int startIndex = 1;
if (!mIs24HourView && isTypedTimeFullyLegal()) {
int keyCode = mTypedTimes.get(mTypedTimes.size() - 1);
if (keyCode == getAmOrPmKeyCode(AM)) {
amOrPm = AM;
} else if (keyCode == getAmOrPmKeyCode(PM)){
amOrPm = PM;
}
startIndex = 2;
}
int minute = -1;
int hour = -1;
for (int i = startIndex; i <= mTypedTimes.size(); i++) {
int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i));
if (i == startIndex) {
minute = val;
} else if (i == startIndex+1) {
minute += 10 * val;
if (enteredZeros != null && val == 0) {
enteredZeros[1] = true;
}
} else if (i == startIndex+2) {
hour = val;
} else if (i == startIndex+3) {
hour += 10 * val;
if (enteredZeros != null && val == 0) {
enteredZeros[0] = true;
}
}
}
return new int[] { hour, minute, amOrPm };
| private java.util.ArrayList | getTypedTimes()
return mTypedTimes;
| private int | getValFromKeyCode(int keyCode)
switch (keyCode) {
case KeyEvent.KEYCODE_0:
return 0;
case KeyEvent.KEYCODE_1:
return 1;
case KeyEvent.KEYCODE_2:
return 2;
case KeyEvent.KEYCODE_3:
return 3;
case KeyEvent.KEYCODE_4:
return 4;
case KeyEvent.KEYCODE_5:
return 5;
case KeyEvent.KEYCODE_6:
return 6;
case KeyEvent.KEYCODE_7:
return 7;
case KeyEvent.KEYCODE_8:
return 8;
case KeyEvent.KEYCODE_9:
return 9;
default:
return -1;
}
| private boolean | inKbMode()
return mInKbMode;
| private void | initialize(int hourOfDay, int minute, boolean is24HourView, int index)
mInitialHourOfDay = hourOfDay;
mInitialMinute = minute;
mIs24HourView = is24HourView;
mInKbMode = false;
updateUI(index);
| public boolean | is24HourView()
return mIs24HourView;
| public boolean | isEnabled()
return mIsEnabled;
| private boolean | isTypedTimeFullyLegal()Check if the time that has been typed so far is completely legal, as is.
if (mIs24HourView) {
// For 24-hour mode, the time is legal if the hours and minutes are each legal. Note:
// getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode.
int[] values = getEnteredTime(null);
return (values[0] >= 0 && values[1] >= 0 && values[1] < 60);
} else {
// For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be
// legally added at specific times based on the tree's algorithm.
return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) ||
mTypedTimes.contains(getAmOrPmKeyCode(PM)));
}
| private boolean | isTypedTimeLegalSoFar()Traverse the tree to see if the keys that have been typed so far are legal as is,
or may become legal as more keys are typed (excluding backspace).
Node node = mLegalTimesTree;
for (int keyCode : mTypedTimes) {
node = node.canReach(keyCode);
if (node == null) {
return false;
}
}
return true;
| private static int | lastIndexOfAny(java.lang.String str, char[] any)
final int lengthAny = any.length;
if (lengthAny > 0) {
for (int i = str.length() - 1; i >= 0; i--) {
char c = str.charAt(i);
for (int j = 0; j < lengthAny; j++) {
if (c == any[j]) {
return i;
}
}
}
}
return -1;
| private static int | modulo12(int n, boolean startWithZero)
int value = n % 12;
if (value == 0 && !startWithZero) {
value = 12;
}
return value;
| public void | onConfigurationChanged(android.content.res.Configuration newConfig)
updateUI(mRadialTimePickerView.getCurrentItemShowing());
| public void | onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
event.setClassName(TimePicker.class.getName());
| public void | onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)
info.setClassName(TimePicker.class.getName());
| public void | onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
int flags = DateUtils.FORMAT_SHOW_TIME;
if (mIs24HourView) {
flags |= DateUtils.FORMAT_24HOUR;
} else {
flags |= DateUtils.FORMAT_12HOUR;
}
mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour());
mTempCalendar.set(Calendar.MINUTE, getCurrentMinute());
String selectedDate = DateUtils.formatDateTime(mContext,
mTempCalendar.getTimeInMillis(), flags);
event.getText().add(selectedDate);
| public void | onRestoreInstanceState(android.os.Parcelable state)
SavedState ss = (SavedState) state;
setInKbMode(ss.inKbMode());
setTypedTimes(ss.getTypesTimes());
initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
mRadialTimePickerView.invalidate();
if (mInKbMode) {
tryStartingKbMode(-1);
mHourView.invalidate();
}
| public android.os.Parcelable | onSaveInstanceState(android.os.Parcelable superState)
return new SavedState(superState, getCurrentHour(), getCurrentMinute(),
is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing());
| private void | onTimeChanged()Propagate the time change
mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
if (mOnTimeChangedListener != null) {
mOnTimeChangedListener.onTimeChanged(mDelegator,
getCurrentHour(), getCurrentMinute());
}
| public void | onValueSelected(int pickerIndex, int newValue, boolean autoAdvance)Called by the picker for updating the header display.
switch (pickerIndex) {
case HOUR_INDEX:
if (mAllowAutoAdvance && autoAdvance) {
updateHeaderHour(newValue, false);
setCurrentItemShowing(MINUTE_INDEX, true, false);
mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
} else {
updateHeaderHour(newValue, true);
}
break;
case MINUTE_INDEX:
updateHeaderMinute(newValue, true);
break;
case AMPM_INDEX:
updateAmPmLabelStates(newValue);
break;
case ENABLE_PICKER_INDEX:
if (!isTypedTimeFullyLegal()) {
mTypedTimes.clear();
}
finishKbMode();
break;
}
if (mOnTimeChangedListener != null) {
mOnTimeChangedListener.onTimeChanged(mDelegator, getCurrentHour(), getCurrentMinute());
}
| private boolean | processKeyUp(int keyCode)For keyboard mode, processes key events.
if (keyCode == KeyEvent.KEYCODE_DEL) {
if (mInKbMode) {
if (!mTypedTimes.isEmpty()) {
int deleted = deleteLastTypedKey();
String deletedKeyStr;
if (deleted == getAmOrPmKeyCode(AM)) {
deletedKeyStr = mAmText;
} else if (deleted == getAmOrPmKeyCode(PM)) {
deletedKeyStr = mPmText;
} else {
deletedKeyStr = String.format("%d", getValFromKeyCode(deleted));
}
mDelegator.announceForAccessibility(
String.format(mDeletedKeyFormat, deletedKeyStr));
updateDisplay(true);
}
}
} else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1
|| keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3
|| keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5
|| keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7
|| keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9
|| (!mIs24HourView &&
(keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) {
if (!mInKbMode) {
if (mRadialTimePickerView == null) {
// Something's wrong, because time picker should definitely not be null.
Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null.");
return true;
}
mTypedTimes.clear();
tryStartingKbMode(keyCode);
return true;
}
// We're already in keyboard mode.
if (addKeyIfLegal(keyCode)) {
updateDisplay(false);
}
return true;
}
return false;
| private void | setAmOrPm(int amOrPm)
updateAmPmLabelStates(amOrPm);
mRadialTimePickerView.setAmOrPm(amOrPm);
| public void | setCurrentHour(java.lang.Integer currentHour)Set the current hour.
if (mInitialHourOfDay == currentHour) {
return;
}
mInitialHourOfDay = currentHour;
updateHeaderHour(currentHour, true);
updateHeaderAmPm();
mRadialTimePickerView.setCurrentHour(currentHour);
mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM);
mDelegator.invalidate();
onTimeChanged();
| private void | setCurrentItemShowing(int index, boolean animateCircle, boolean announce)Show either Hours or Minutes.
mRadialTimePickerView.setCurrentItemShowing(index, animateCircle);
if (index == HOUR_INDEX) {
if (announce) {
mDelegator.announceForAccessibility(mSelectHours);
}
} else {
if (announce) {
mDelegator.announceForAccessibility(mSelectMinutes);
}
}
mHourView.setSelected(index == HOUR_INDEX);
mMinuteView.setSelected(index == MINUTE_INDEX);
| public void | setCurrentLocale(java.util.Locale locale)
super.setCurrentLocale(locale);
mTempCalendar = Calendar.getInstance(locale);
| public void | setCurrentMinute(java.lang.Integer currentMinute)Set the current minute (0-59).
if (mInitialMinute == currentMinute) {
return;
}
mInitialMinute = currentMinute;
updateHeaderMinute(currentMinute, true);
mRadialTimePickerView.setCurrentMinute(currentMinute);
mDelegator.invalidate();
onTimeChanged();
| public void | setEnabled(boolean enabled)
mHourView.setEnabled(enabled);
mMinuteView.setEnabled(enabled);
mAmLabel.setEnabled(enabled);
mPmLabel.setEnabled(enabled);
mRadialTimePickerView.setEnabled(enabled);
mIsEnabled = enabled;
| private void | setInKbMode(boolean inKbMode)Set whether in keyboard mode or not.
mInKbMode = inKbMode;
| public void | setIs24HourView(java.lang.Boolean is24HourView)Set whether in 24 hour or AM/PM mode.
if (is24HourView == mIs24HourView) {
return;
}
mIs24HourView = is24HourView;
generateLegalTimesTree();
int hour = mRadialTimePickerView.getCurrentHour();
mInitialHourOfDay = hour;
updateHeaderHour(hour, false);
updateHeaderAmPm();
updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing());
mDelegator.invalidate();
| public void | setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback)
mOnTimeChangedListener = callback;
| private void | setTypedTimes(java.util.ArrayList typeTimes)
mTypedTimes = typeTimes;
| private void | setupListeners()
mHeaderView.setOnKeyListener(mKeyListener);
mHeaderView.setOnFocusChangeListener(mFocusListener);
mHeaderView.setFocusable(true);
mRadialTimePickerView.setOnValueSelectedListener(this);
| private void | tryAnnounceForAccessibility(java.lang.CharSequence text, boolean isHour)
if (mLastAnnouncedIsHour != isHour || !text.equals(mLastAnnouncedText)) {
// TODO: Find a better solution, potentially live regions?
mDelegator.announceForAccessibility(text);
mLastAnnouncedText = text;
mLastAnnouncedIsHour = isHour;
}
| private void | tryStartingKbMode(int keyCode)Try to start keyboard mode with the specified key.
if (keyCode == -1 || addKeyIfLegal(keyCode)) {
mInKbMode = true;
onValidationChanged(false);
updateDisplay(false);
mRadialTimePickerView.setInputEnabled(false);
}
| private void | tryVibrate()
mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
| private void | updateAmPmLabelStates(int amOrPm)
final boolean isAm = amOrPm == AM;
mAmLabel.setChecked(isAm);
mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha);
final boolean isPm = amOrPm == PM;
mPmLabel.setChecked(isPm);
mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha);
| private void | updateDisplay(boolean allowEmptyDisplay)Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is
empty, either show an empty display (filled with the placeholder text), or update from the
timepicker's values.
if (!allowEmptyDisplay && mTypedTimes.isEmpty()) {
int hour = mRadialTimePickerView.getCurrentHour();
int minute = mRadialTimePickerView.getCurrentMinute();
updateHeaderHour(hour, false);
updateHeaderMinute(minute, false);
if (!mIs24HourView) {
updateAmPmLabelStates(hour < 12 ? AM : PM);
}
setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true);
onValidationChanged(true);
} else {
boolean[] enteredZeros = {false, false};
int[] values = getEnteredTime(enteredZeros);
String hourFormat = enteredZeros[0] ? "%02d" : "%2d";
String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d";
String hourStr = (values[0] == -1) ? mDoublePlaceholderText :
String.format(hourFormat, values[0]).replace(' ", mPlaceholderText);
String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
String.format(minuteFormat, values[1]).replace(' ", mPlaceholderText);
mHourView.setText(hourStr);
mHourView.setSelected(false);
mMinuteView.setText(minuteStr);
mMinuteView.setSelected(false);
if (!mIs24HourView) {
updateAmPmLabelStates(values[2]);
}
}
| private void | updateHeaderAmPm()
if (mIs24HourView) {
mAmPmLayout.setVisibility(View.GONE);
} else {
// Ensure that AM/PM layout is in the correct position.
final String dateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, "hm");
final boolean amPmAtStart = dateTimePattern.startsWith("a");
final ViewGroup parent = (ViewGroup) mAmPmLayout.getParent();
final int targetIndex = amPmAtStart ? 0 : parent.getChildCount() - 1;
final int currentIndex = parent.indexOfChild(mAmPmLayout);
if (targetIndex != currentIndex) {
parent.removeView(mAmPmLayout);
parent.addView(mAmPmLayout, targetIndex);
}
updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
}
| private void | updateHeaderHour(int value, boolean announce)
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
(mIs24HourView) ? "Hm" : "hm");
final int lengthPattern = bestDateTimePattern.length();
boolean hourWithTwoDigit = false;
char hourFormat = '\0";
// Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
// the hour format that we found.
for (int i = 0; i < lengthPattern; i++) {
final char c = bestDateTimePattern.charAt(i);
if (c == 'H" || c == 'h" || c == 'K" || c == 'k") {
hourFormat = c;
if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
hourWithTwoDigit = true;
}
break;
}
}
final String format;
if (hourWithTwoDigit) {
format = "%02d";
} else {
format = "%d";
}
if (mIs24HourView) {
// 'k' means 1-24 hour
if (hourFormat == 'k" && value == 0) {
value = 24;
}
} else {
// 'K' means 0-11 hour
value = modulo12(value, hourFormat == 'K");
}
CharSequence text = String.format(format, value);
mHourView.setText(text);
if (announce) {
tryAnnounceForAccessibility(text, true);
}
| private void | updateHeaderMinute(int value, boolean announceForAccessibility)
if (value == 60) {
value = 0;
}
final CharSequence text = String.format(mCurrentLocale, "%02d", value);
mMinuteView.setText(text);
if (announceForAccessibility) {
tryAnnounceForAccessibility(text, false);
}
| private void | updateHeaderSeparator()The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
See http://unicode.org/cldr/trac/browser/trunk/common/main
We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
separator as the character which is just after the hour marker in the returned pattern.
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
(mIs24HourView) ? "Hm" : "hm");
final String separatorText;
// See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats
final char[] hourFormats = {'H", 'h", 'K", 'k"};
int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats);
if (hIndex == -1) {
// Default case
separatorText = ":";
} else {
separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
}
mSeparatorView.setText(separatorText);
| private void | updateRadialPicker(int index)
mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView);
setCurrentItemShowing(index, false, true);
| private void | updateUI(int index)
// Update RadialPicker values
updateRadialPicker(index);
// Enable or disable the AM/PM view.
updateHeaderAmPm();
// Update Hour and Minutes
updateHeaderHour(mInitialHourOfDay, false);
// Update time separator
updateHeaderSeparator();
// Update Minutes
updateHeaderMinute(mInitialMinute, false);
// Invalidate everything
mDelegator.invalidate();
|
|