diff options
| author | Phil Weaver <pweaver@google.com> | 2017-04-26 12:58:15 -0700 |
|---|---|---|
| committer | Phil Weaver <pweaver@google.com> | 2017-05-02 10:43:34 -0700 |
| commit | 1d359a6d3179b7e793fc4082237b001d7260c423 (patch) | |
| tree | 970de8dd605bedba77d229dcc9f21f20cd1335c1 /core/java/android/widget/NumberPicker.java | |
| parent | da3dd7c0cf1fcd7e352c8f9e30519e85776c5662 (diff) | |
NumberPicker a11y (and a11y-inspired) fixes
- Sending scroll events for accessibility.
- Sending text update events when state changes.
- Blocking text updates during fling to reduce number of events.
- Making widget focusable by default, which keeps focus from
moving to the rest of the UI when the text box becomes invisible.
- Managing visibility of the text box alongside IME state, so the
IME won't decide to display the password keyboard during a fling.
Bug: 21494380
Bug: 37016501
Test: Ran NumberPicker CTS
Change-Id: I459d37d4a54c91e1cb5c7ec68fe0f012b25fb740
Diffstat (limited to 'core/java/android/widget/NumberPicker.java')
| -rw-r--r-- | core/java/android/widget/NumberPicker.java | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 7bdd6dadf415..d456989eb50a 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -737,6 +737,7 @@ public class NumberPicker extends LinearLayout { mInputText.setFilters(new InputFilter[] { new InputTextFilter() }); + mInputText.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE); @@ -770,6 +771,12 @@ public class NumberPicker extends LinearLayout { if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } + + // Should be focusable by default, as the text view whose visibility changes is focusable + if (getFocusable() == View.FOCUSABLE_AUTO) { + setFocusable(View.FOCUSABLE); + setFocusableInTouchMode(true); + } } @Override @@ -856,7 +863,7 @@ public class NumberPicker extends LinearLayout { switch (action) { case MotionEvent.ACTION_DOWN: { removeAllCallbacks(); - mInputText.setVisibility(View.INVISIBLE); + hideSoftInput(); mLastDownOrMoveEventY = mLastDownEventY = event.getY(); mLastDownEventTime = event.getEventTime(); mIgnoreMoveEvents = false; @@ -883,11 +890,9 @@ public class NumberPicker extends LinearLayout { mFlingScroller.forceFinished(true); mAdjustScroller.forceFinished(true); } else if (mLastDownEventY < mTopSelectionDividerTop) { - hideSoftInput(); postChangeCurrentByOneFromLongPress( false, ViewConfiguration.getLongPressTimeout()); } else if (mLastDownEventY > mBottomSelectionDividerBottom) { - hideSoftInput(); postChangeCurrentByOneFromLongPress( true, ViewConfiguration.getLongPressTimeout()); } else { @@ -1120,6 +1125,7 @@ public class NumberPicker extends LinearLayout { @Override public void scrollBy(int x, int y) { int[] selectorIndices = mSelectorIndices; + int startScrollOffset = mCurrentScrollOffset; if (!mWrapSelectorWheel && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { mCurrentScrollOffset = mInitialScrollOffset; @@ -1147,6 +1153,9 @@ public class NumberPicker extends LinearLayout { mCurrentScrollOffset = mInitialScrollOffset; } } + if (startScrollOffset != mCurrentScrollOffset) { + onScrollChanged(0, mCurrentScrollOffset, 0, startScrollOffset); + } } @Override @@ -1735,7 +1744,10 @@ public class NumberPicker extends LinearLayout { } int previous = mValue; mValue = current; - updateInputTextView(); + // If we're flinging, we'll update the text view at the end when it becomes visible + if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) { + updateInputTextView(); + } if (notifyChange) { notifyChange(previous, current); } @@ -1752,7 +1764,7 @@ public class NumberPicker extends LinearLayout { */ private void changeValueByOne(boolean increment) { if (mHasSelectorWheel) { - mInputText.setVisibility(View.INVISIBLE); + hideSoftInput(); if (!moveToFinalScrollerPosition(mFlingScroller)) { moveToFinalScrollerPosition(mAdjustScroller); } @@ -1799,9 +1811,8 @@ public class NumberPicker extends LinearLayout { */ private void onScrollerFinished(Scroller scroller) { if (scroller == mFlingScroller) { - if (!ensureScrollWheelAdjusted()) { - updateInputTextView(); - } + ensureScrollWheelAdjusted(); + updateInputTextView(); onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); } else { if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { @@ -1937,9 +1948,25 @@ public class NumberPicker extends LinearLayout { */ String text = (mDisplayedValues == null) ? formatNumber(mValue) : mDisplayedValues[mValue - mMinValue]; - if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) { - mInputText.setText(text); - return true; + if (!TextUtils.isEmpty(text)) { + CharSequence beforeText = mInputText.getText(); + if (!text.equals(beforeText.toString())) { + mInputText.setText(text); + if (mAccessibilityNodeProvider != null) { + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + mInputText.onInitializeAccessibilityEvent(event); + mInputText.onPopulateAccessibilityEvent(event); + event.setFromIndex(0); + event.setRemovedCount(beforeText.length()); + event.setAddedCount(text.length()); + event.setBeforeText(beforeText); + event.setSource(NumberPicker.this, + AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INPUT); + requestSendAccessibilityEvent(NumberPicker.this, event); + } + return true; + } } return false; |
