Merge "DatePicker crashes when going from 2036 to 2035 via ▼" into ics-mr0
This commit is contained in:
committed by
Android (Google) Code Review
commit
5dc30a770a
@ -32,6 +32,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.NumberPicker.OnValueChangeListener;
|
||||
|
||||
import com.android.internal.R;
|
||||
@ -90,6 +91,12 @@ public class DatePicker extends FrameLayout {
|
||||
|
||||
private final NumberPicker mYearSpinner;
|
||||
|
||||
private final EditText mDaySpinnerInput;
|
||||
|
||||
private final EditText mMonthSpinnerInput;
|
||||
|
||||
private final EditText mYearSpinnerInput;
|
||||
|
||||
private final CalendarView mCalendarView;
|
||||
|
||||
private Locale mCurrentLocale;
|
||||
@ -164,6 +171,7 @@ public class DatePicker extends FrameLayout {
|
||||
|
||||
OnValueChangeListener onChangeListener = new OnValueChangeListener() {
|
||||
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
||||
updateInputState();
|
||||
mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
|
||||
// take care of wrapping of days and months to update greater fields
|
||||
if (picker == mDaySpinner) {
|
||||
@ -214,6 +222,7 @@ public class DatePicker extends FrameLayout {
|
||||
mDaySpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
|
||||
mDaySpinner.setOnLongPressUpdateInterval(100);
|
||||
mDaySpinner.setOnValueChangedListener(onChangeListener);
|
||||
mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
|
||||
|
||||
// month
|
||||
mMonthSpinner = (NumberPicker) findViewById(R.id.month);
|
||||
@ -222,11 +231,13 @@ public class DatePicker extends FrameLayout {
|
||||
mMonthSpinner.setDisplayedValues(mShortMonths);
|
||||
mMonthSpinner.setOnLongPressUpdateInterval(200);
|
||||
mMonthSpinner.setOnValueChangedListener(onChangeListener);
|
||||
mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
|
||||
|
||||
// year
|
||||
mYearSpinner = (NumberPicker) findViewById(R.id.year);
|
||||
mYearSpinner.setOnLongPressUpdateInterval(100);
|
||||
mYearSpinner.setOnValueChangedListener(onChangeListener);
|
||||
mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
|
||||
|
||||
// show only what the user required but make sure we
|
||||
// show something and the spinners have higher priority
|
||||
@ -709,6 +720,27 @@ public class DatePicker extends FrameLayout {
|
||||
mYearSpinner.findViewById(R.id.decrement).setContentDescription(text);
|
||||
}
|
||||
|
||||
private void updateInputState() {
|
||||
// Make sure that if the user changes the value and the IME is active
|
||||
// for one of the inputs if this widget, the IME is closed. If the user
|
||||
// changed the value via the IME and there is a next input the IME will
|
||||
// be shown, otherwise the user chose another means of changing the
|
||||
// value and having the IME up makes no sense.
|
||||
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
|
||||
if (inputMethodManager != null) {
|
||||
if (inputMethodManager.isActive(mYearSpinnerInput)) {
|
||||
mYearSpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
} else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
|
||||
mMonthSpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
} else if (inputMethodManager.isActive(mDaySpinnerInput)) {
|
||||
mDaySpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for managing state storing/restoring.
|
||||
*/
|
||||
|
@ -536,6 +536,10 @@ public class NumberPicker extends LinearLayout {
|
||||
|
||||
OnClickListener onClickListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
|
||||
if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) {
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
}
|
||||
mInputText.clearFocus();
|
||||
if (v.getId() == R.id.increment) {
|
||||
changeCurrentByOne(true);
|
||||
@ -571,17 +575,14 @@ public class NumberPicker extends LinearLayout {
|
||||
mInputText = (EditText) findViewById(R.id.numberpicker_input);
|
||||
mInputText.setOnFocusChangeListener(new OnFocusChangeListener() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
|
||||
if (hasFocus) {
|
||||
mInputText.selectAll();
|
||||
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
|
||||
if (inputMethodManager != null) {
|
||||
inputMethodManager.showSoftInput(mInputText, 0);
|
||||
}
|
||||
} else {
|
||||
mInputText.setSelection(0, 0);
|
||||
if (inputMethodManager != null) {
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
}
|
||||
validateInputTextView(v);
|
||||
}
|
||||
}
|
||||
@ -996,17 +997,14 @@ public class NumberPicker extends LinearLayout {
|
||||
* enabled.
|
||||
* </p>
|
||||
*
|
||||
* @param wrapSelector Whether to wrap.
|
||||
* @param wrapSelectorWheel Whether to wrap.
|
||||
*/
|
||||
public void setWrapSelectorWheel(boolean wrapSelector) {
|
||||
if (wrapSelector && (mMaxValue - mMinValue) < mSelectorIndices.length) {
|
||||
public void setWrapSelectorWheel(boolean wrapSelectorWheel) {
|
||||
if (wrapSelectorWheel && (mMaxValue - mMinValue) < mSelectorIndices.length) {
|
||||
throw new IllegalStateException("Range less than selector items count.");
|
||||
}
|
||||
if (wrapSelector != mWrapSelectorWheel) {
|
||||
// force the selector indices array to be reinitialized
|
||||
mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE;
|
||||
mWrapSelectorWheel = wrapSelector;
|
||||
// force redraw since we might look different
|
||||
if (wrapSelectorWheel != mWrapSelectorWheel) {
|
||||
mWrapSelectorWheel = wrapSelectorWheel;
|
||||
updateIncrementAndDecrementButtonsVisibilityState();
|
||||
}
|
||||
}
|
||||
@ -1206,7 +1204,13 @@ public class NumberPicker extends LinearLayout {
|
||||
for (int i = 0; i < selectorIndices.length; i++) {
|
||||
int selectorIndex = selectorIndices[i];
|
||||
String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex);
|
||||
canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint);
|
||||
// Do not draw the middle item if input is visible since the input is shown only
|
||||
// if the wheel is static and it covers the middle item. Otherwise, if the user
|
||||
// starts editing the text via the IME he may see a dimmed version of the old
|
||||
// value intermixed with the new one.
|
||||
if (i != SELECTOR_MIDDLE_ITEM_INDEX || mInputText.getVisibility() != VISIBLE) {
|
||||
canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint);
|
||||
}
|
||||
y += mSelectorElementHeight;
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,8 @@ import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.NumberPicker.OnValueChangeListener;
|
||||
|
||||
import com.android.internal.R;
|
||||
@ -79,6 +79,12 @@ public class TimePicker extends FrameLayout {
|
||||
|
||||
private final NumberPicker mAmPmSpinner;
|
||||
|
||||
private final EditText mHourSpinnerInput;
|
||||
|
||||
private final EditText mMinuteSpinnerInput;
|
||||
|
||||
private final EditText mAmPmSpinnerInput;
|
||||
|
||||
private final TextView mDivider;
|
||||
|
||||
// Note that the legacy implementation of the TimePicker is
|
||||
@ -140,6 +146,7 @@ public class TimePicker extends FrameLayout {
|
||||
mHourSpinner = (NumberPicker) findViewById(R.id.hour);
|
||||
mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
|
||||
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
|
||||
updateInputState();
|
||||
if (!is24HourView()) {
|
||||
if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY)
|
||||
|| (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) {
|
||||
@ -150,8 +157,8 @@ public class TimePicker extends FrameLayout {
|
||||
onTimeChanged();
|
||||
}
|
||||
});
|
||||
EditText hourInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
|
||||
hourInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
|
||||
mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
|
||||
// divider (only for the new widget style)
|
||||
mDivider = (TextView) findViewById(R.id.divider);
|
||||
@ -167,6 +174,7 @@ public class TimePicker extends FrameLayout {
|
||||
mMinuteSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
|
||||
mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
|
||||
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
|
||||
updateInputState();
|
||||
int minValue = mMinuteSpinner.getMinValue();
|
||||
int maxValue = mMinuteSpinner.getMaxValue();
|
||||
if (oldVal == maxValue && newVal == minValue) {
|
||||
@ -187,8 +195,8 @@ public class TimePicker extends FrameLayout {
|
||||
onTimeChanged();
|
||||
}
|
||||
});
|
||||
EditText minuteInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
|
||||
minuteInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
|
||||
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
|
||||
/* Get the localized am/pm strings and use them in the spinner */
|
||||
mAmPmStrings = new DateFormatSymbols().getAmPmStrings();
|
||||
@ -197,6 +205,7 @@ public class TimePicker extends FrameLayout {
|
||||
View amPmView = findViewById(R.id.amPm);
|
||||
if (amPmView instanceof Button) {
|
||||
mAmPmSpinner = null;
|
||||
mAmPmSpinnerInput = null;
|
||||
mAmPmButton = (Button) amPmView;
|
||||
mAmPmButton.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View button) {
|
||||
@ -213,13 +222,14 @@ public class TimePicker extends FrameLayout {
|
||||
mAmPmSpinner.setDisplayedValues(mAmPmStrings);
|
||||
mAmPmSpinner.setOnValueChangedListener(new OnValueChangeListener() {
|
||||
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
||||
updateInputState();
|
||||
picker.requestFocus();
|
||||
mIsAm = !mIsAm;
|
||||
updateAmPmControl();
|
||||
}
|
||||
});
|
||||
EditText amPmInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
|
||||
amPmInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
|
||||
mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
}
|
||||
|
||||
// update controls to initial state
|
||||
@ -319,7 +329,7 @@ public class TimePicker extends FrameLayout {
|
||||
dest.writeInt(mMinute);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SuppressWarnings({"unused", "hiding"})
|
||||
public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
@ -524,4 +534,25 @@ public class TimePicker extends FrameLayout {
|
||||
mAmPmSpinner.findViewById(R.id.decrement).setContentDescription(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInputState() {
|
||||
// Make sure that if the user changes the value and the IME is active
|
||||
// for one of the inputs if this widget, the IME is closed. If the user
|
||||
// changed the value via the IME and there is a next input the IME will
|
||||
// be shown, otherwise the user chose another means of changing the
|
||||
// value and having the IME up makes no sense.
|
||||
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
|
||||
if (inputMethodManager != null) {
|
||||
if (inputMethodManager.isActive(mHourSpinnerInput)) {
|
||||
mHourSpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
} else if (inputMethodManager.isActive(mMinuteSpinnerInput)) {
|
||||
mMinuteSpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
} else if (inputMethodManager.isActive(mAmPmSpinnerInput)) {
|
||||
mAmPmSpinnerInput.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user