summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Felipe Leme <felipeal@google.com> 2017-08-10 18:38:44 -0700
committer Felipe Leme <felipeal@google.com> 2017-08-15 10:42:58 -0700
commitf480e8cad5e6cf4fed85a944adc01d96f51e966b (patch)
treeb397ded5cfbc6eb89f0085fd880e1e81d290691f
parent144d8cb6261b831bebcd2adb1ed73c1e9298190a (diff)
Improved autofill support on DatePicker and TimePicker:
- Save autofilled value so UI is properly highlighted. - Notify TimePicker listener just once. Test: cts-tradefed run commandAndExit cts-dev -m CtsAutoFillServiceTestCases Test: cts-tradefed run commandAndExit cts-dev -m CtsWidgetTestCases -t android.widget.cts.DatePickerTest Test: cts-tradefed run commandAndExit cts-dev -m CtsWidgetTestCases -t android.widget.cts.TimePickerTest Fixes: 37098837 Change-Id: I38d64c107f6059b94c92676ea37681006474f519
-rw-r--r--core/java/android/widget/DatePicker.java52
-rwxr-xr-xcore/java/android/widget/DatePickerCalendarDelegate.java15
-rw-r--r--core/java/android/widget/DatePickerSpinnerDelegate.java1
-rw-r--r--core/java/android/widget/TimePicker.java59
-rw-r--r--core/java/android/widget/TimePickerClockDelegate.java35
-rw-r--r--core/java/android/widget/TimePickerSpinnerDelegate.java18
6 files changed, 131 insertions, 49 deletions
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 8094bfc6eeb8..dfb36423ea94 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -524,12 +524,13 @@ public class DatePicker extends FrameLayout {
void setAutoFillChangeListener(OnDateChangedListener onDateChangedListener);
void updateDate(int year, int month, int dayOfMonth);
- void updateDate(long date);
int getYear();
int getMonth();
int getDayOfMonth();
- long getDate();
+
+ void autofill(AutofillValue value);
+ AutofillValue getAutofillValue();
void setFirstDayOfWeek(int firstDayOfWeek);
int getFirstDayOfWeek();
@@ -572,6 +573,7 @@ public class DatePicker extends FrameLayout {
// The context
protected Context mContext;
+ // NOTE: when subclasses change this variable, they must call resetAutofilledValue().
protected Calendar mCurrentDate;
// The current locale
@@ -582,6 +584,11 @@ public class DatePicker extends FrameLayout {
protected OnDateChangedListener mAutoFillChangeListener;
protected ValidationCallback mValidationCallback;
+ // The value that was passed to autofill() - it must be stored because it getAutofillValue()
+ // must return the exact same value that was autofilled, otherwise the widget will not be
+ // properly highlighted after autofill().
+ private long mAutofilledValue;
+
public AbstractDatePickerDelegate(DatePicker delegator, Context context) {
mDelegator = delegator;
mContext = context;
@@ -612,16 +619,38 @@ public class DatePicker extends FrameLayout {
}
@Override
- public void updateDate(long date) {
- Calendar cal = Calendar.getInstance(mCurrentLocale);
- cal.setTimeInMillis(date);
+ public final void autofill(AutofillValue value) {
+ if (value == null || !value.isDate()) {
+ Log.w(LOG_TAG, value + " could not be autofilled into " + this);
+ return;
+ }
+
+ final long time = value.getDateValue();
+
+ final Calendar cal = Calendar.getInstance(mCurrentLocale);
+ cal.setTimeInMillis(time);
updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH));
+
+ // Must set mAutofilledValue *after* calling subclass method to make sure the value
+ // returned by getAutofillValue() matches it.
+ mAutofilledValue = time;
}
@Override
- public long getDate() {
- return mCurrentDate.getTimeInMillis();
+ public final AutofillValue getAutofillValue() {
+ final long time = mAutofilledValue != 0
+ ? mAutofilledValue
+ : mCurrentDate.getTimeInMillis();
+ return AutofillValue.forDate(time);
+ }
+
+ /**
+ * This method must be called every time the value of the year, month, and/or day is
+ * changed by a subclass method.
+ */
+ protected void resetAutofilledValue() {
+ mAutofilledValue = 0;
}
protected void onValidationChanged(boolean valid) {
@@ -777,12 +806,7 @@ public class DatePicker extends FrameLayout {
public void autofill(AutofillValue value) {
if (!isEnabled()) return;
- if (!value.isDate()) {
- Log.w(LOG_TAG, value + " could not be autofilled into " + this);
- return;
- }
-
- mDelegate.updateDate(value.getDateValue());
+ mDelegate.autofill(value);
}
@Override
@@ -792,6 +816,6 @@ public class DatePicker extends FrameLayout {
@Override
public AutofillValue getAutofillValue() {
- return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null;
+ return isEnabled() ? mDelegate.getAutofillValue() : null;
}
}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 636519b197e7..60b4757216af 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -368,12 +368,9 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
}
@Override
- public void init(int year, int monthOfYear, int dayOfMonth,
+ public void init(int year, int month, int dayOfMonth,
DatePicker.OnDateChangedListener callBack) {
- mCurrentDate.set(Calendar.YEAR, year);
- mCurrentDate.set(Calendar.MONTH, monthOfYear);
- mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-
+ setDate(year, month, dayOfMonth);
onDateChanged(false, false);
mOnDateChangedListener = callBack;
@@ -381,11 +378,15 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
@Override
public void updateDate(int year, int month, int dayOfMonth) {
+ setDate(year, month, dayOfMonth);
+ onDateChanged(false, true);
+ }
+
+ private void setDate(int year, int month, int dayOfMonth) {
mCurrentDate.set(Calendar.YEAR, year);
mCurrentDate.set(Calendar.MONTH, month);
mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-
- onDateChanged(false, true);
+ resetAutofilledValue();
}
private void onDateChanged(boolean fromUser, boolean callbackToClient) {
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index 4f9316f881cd..dba74b191b09 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -504,6 +504,7 @@ class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
private void setDate(int year, int month, int dayOfMonth) {
mCurrentDate.set(year, month, dayOfMonth);
+ resetAutofilledValue();
if (mCurrentDate.before(mMinDate)) {
mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
} else if (mCurrentDate.after(mMaxDate)) {
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index de289bb9a27a..ae6881e4e28c 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -366,8 +366,11 @@ public class TimePicker extends FrameLayout {
void setMinute(@IntRange(from = 0, to = 59) int minute);
int getMinute();
- void setDate(long date);
- long getDate();
+ void setDate(@IntRange(from = 0, to = 23) int hour,
+ @IntRange(from = 0, to = 59) int minute);
+
+ void autofill(AutofillValue value);
+ AutofillValue getAutofillValue();
void setIs24Hour(boolean is24Hour);
boolean is24Hour();
@@ -422,6 +425,11 @@ public class TimePicker extends FrameLayout {
protected OnTimeChangedListener mOnTimeChangedListener;
protected OnTimeChangedListener mAutoFillChangeListener;
+ // The value that was passed to autofill() - it must be stored because it getAutofillValue()
+ // must return the exact same value that was autofilled, otherwise the widget will not be
+ // properly highlighted after autofill().
+ private long mAutofilledValue;
+
public AbstractTimePickerDelegate(@NonNull TimePicker delegator, @NonNull Context context) {
mDelegator = delegator;
mContext = context;
@@ -439,19 +447,41 @@ public class TimePicker extends FrameLayout {
}
@Override
- public void setDate(long date) {
- Calendar cal = Calendar.getInstance(mLocale);
- cal.setTimeInMillis(date);
- setHour(cal.get(Calendar.HOUR_OF_DAY));
- setMinute(cal.get(Calendar.MINUTE));
+ public final void autofill(AutofillValue value) {
+ if (value == null || !value.isDate()) {
+ Log.w(LOG_TAG, value + " could not be autofilled into " + this);
+ return;
+ }
+
+ final long time = value.getDateValue();
+
+ final Calendar cal = Calendar.getInstance(mLocale);
+ cal.setTimeInMillis(time);
+ setDate(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
+
+ // Must set mAutofilledValue *after* calling subclass method to make sure the value
+ // returned by getAutofillValue() matches it.
+ mAutofilledValue = time;
}
@Override
- public long getDate() {
- Calendar cal = Calendar.getInstance(mLocale);
+ public final AutofillValue getAutofillValue() {
+ if (mAutofilledValue != 0) {
+ return AutofillValue.forDate(mAutofilledValue);
+ }
+
+ final Calendar cal = Calendar.getInstance(mLocale);
cal.set(Calendar.HOUR_OF_DAY, getHour());
cal.set(Calendar.MINUTE, getMinute());
- return cal.getTimeInMillis();
+ return AutofillValue.forDate(cal.getTimeInMillis());
+ }
+
+ /**
+ * This method must be called every time the value of the hour and/or minute is changed by
+ * a subclass method.
+ */
+ protected void resetAutofilledValue() {
+ mAutofilledValue = 0;
}
protected static class SavedState extends View.BaseSavedState {
@@ -532,12 +562,7 @@ public class TimePicker extends FrameLayout {
public void autofill(AutofillValue value) {
if (!isEnabled()) return;
- if (!value.isDate()) {
- Log.w(LOG_TAG, value + " could not be autofilled into " + this);
- return;
- }
-
- mDelegate.setDate(value.getDateValue());
+ mDelegate.autofill(value);
}
@Override
@@ -547,6 +572,6 @@ public class TimePicker extends FrameLayout {
@Override
public AutofillValue getAutofillValue() {
- return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null;
+ return isEnabled() ? mDelegate.getAutofillValue() : null;
}
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 526246b28530..706b0ce225dc 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -506,19 +506,29 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
mAmPmLayout.setLayoutParams(params);
}
+ @Override
+ public void setDate(int hour, int minute) {
+ setHourInternal(hour, FROM_EXTERNAL_API, true, false);
+ setMinuteInternal(minute, FROM_EXTERNAL_API, false);
+
+ onTimeChanged();
+ }
+
/**
* Set the current hour.
*/
@Override
public void setHour(int hour) {
- setHourInternal(hour, FROM_EXTERNAL_API, true);
+ setHourInternal(hour, FROM_EXTERNAL_API, true, true);
}
- private void setHourInternal(int hour, @ChangeSource int source, boolean announce) {
+ private void setHourInternal(int hour, @ChangeSource int source, boolean announce,
+ boolean notify) {
if (mCurrentHour == hour) {
return;
}
+ resetAutofilledValue();
mCurrentHour = hour;
updateHeaderHour(hour, announce);
updateHeaderAmPm();
@@ -532,7 +542,9 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
}
mDelegator.invalidate();
- onTimeChanged();
+ if (notify) {
+ onTimeChanged();
+ }
}
/**
@@ -557,14 +569,15 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
*/
@Override
public void setMinute(int minute) {
- setMinuteInternal(minute, FROM_EXTERNAL_API);
+ setMinuteInternal(minute, FROM_EXTERNAL_API, true);
}
- private void setMinuteInternal(int minute, @ChangeSource int source) {
+ private void setMinuteInternal(int minute, @ChangeSource int source, boolean notify) {
if (mCurrentMinute == minute) {
return;
}
+ resetAutofilledValue();
mCurrentMinute = minute;
updateHeaderMinute(minute, true);
@@ -576,7 +589,9 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
}
mDelegator.invalidate();
- onTimeChanged();
+ if (notify) {
+ onTimeChanged();
+ }
}
/**
@@ -870,7 +885,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
valueChanged = true;
}
final boolean isTransition = mAllowAutoAdvance && autoAdvance;
- setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition);
+ setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition, true);
if (isTransition) {
setCurrentItemShowing(MINUTE_INDEX, true, false);
@@ -882,7 +897,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
if (getMinute() != newValue) {
valueChanged = true;
}
- setMinuteInternal(newValue, FROM_RADIAL_PICKER);
+ setMinuteInternal(newValue, FROM_RADIAL_PICKER, true);
break;
}
@@ -897,10 +912,10 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
public void onValueChanged(int pickerType, int newValue) {
switch (pickerType) {
case TextInputTimePickerView.HOURS:
- setHourInternal(newValue, FROM_INPUT_PICKER, false);
+ setHourInternal(newValue, FROM_INPUT_PICKER, false, true);
break;
case TextInputTimePickerView.MINUTES:
- setMinuteInternal(newValue, FROM_INPUT_PICKER);
+ setMinuteInternal(newValue, FROM_INPUT_PICKER, true);
break;
case TextInputTimePickerView.AMPM:
setAmOrPm(newValue);
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 7a7d9a948dcc..cc79b9c85784 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -284,6 +284,14 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate {
}
@Override
+ public void setDate(int hour, int minute) {
+ setCurrentHour(hour, false);
+ setCurrentMinute(minute, false);
+
+ onTimeChanged();
+ }
+
+ @Override
public void setHour(int hour) {
setCurrentHour(hour, true);
}
@@ -293,6 +301,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate {
if (currentHour == getHour()) {
return;
}
+ resetAutofilledValue();
if (!is24Hour()) {
// convert [0,23] ordinal to wall clock display
if (currentHour >= HOURS_IN_HALF_DAY) {
@@ -328,11 +337,18 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate {
@Override
public void setMinute(int minute) {
+ setCurrentMinute(minute, true);
+ }
+
+ private void setCurrentMinute(int minute, boolean notifyTimeChanged) {
if (minute == getMinute()) {
return;
}
+ resetAutofilledValue();
mMinuteSpinner.setValue(minute);
- onTimeChanged();
+ if (notifyTimeChanged) {
+ onTimeChanged();
+ }
}
@Override