Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d359a6d authored by Phil Weaver's avatar Phil Weaver
Browse files

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
parent da3dd7c0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -630,7 +630,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
    public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;

    /**
     * Represents the event of scrolling a view.
     * Represents the event of scrolling a view. This event type is generally not sent directly.
     * @see View#onScrollChanged(int, int, int, int)
     */
    public static final int TYPE_VIEW_SCROLLED = 0x00001000;

+38 −11
Original line number Diff line number Diff line
@@ -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;
        // 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()) {
            ensureScrollWheelAdjusted();
            updateInputTextView();
            }
            onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
        } else {
            if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
@@ -1937,10 +1948,26 @@ public class NumberPicker extends LinearLayout {
         */
        String text = (mDisplayedValues == null) ? formatNumber(mValue)
                : mDisplayedValues[mValue - mMinValue];
        if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) {
        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;
    }