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

Commit 2b94bbed 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.

This CL re-merges change I459d37d4a54c91e1cb5c7ec68fe0f012b25fb740
but includes a fix to hide the visibility of the input text field
whenever the keyboard needs to be hidden, even if the keyboard
is not being shown or the text box isn't active. That removes an
undesirable visual side-effect of the previous change. This CL
also has a more correct decision about when to send a text change
accessibility event.

Bug: 21494380
Bug: 37016501
Test: Ran NumberPicker CTS, including a new change.
Change-Id: I04c49ddc2f877cd019ee355c722c81dcd3ba0dda
parent df99c779
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -620,7 +620,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
    public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
    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;
    public static final int TYPE_VIEW_SCROLLED = 0x00001000;


+41 −14
Original line number Original line Diff line number Diff line
@@ -737,6 +737,7 @@ public class NumberPicker extends LinearLayout {
        mInputText.setFilters(new InputFilter[] {
        mInputText.setFilters(new InputFilter[] {
            new InputTextFilter()
            new InputTextFilter()
        });
        });
        mInputText.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);


        mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
        mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
        mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE);
        mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE);
@@ -770,6 +771,12 @@ public class NumberPicker extends LinearLayout {
        if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
        if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            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
    @Override
@@ -856,7 +863,7 @@ public class NumberPicker extends LinearLayout {
        switch (action) {
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
            case MotionEvent.ACTION_DOWN: {
                removeAllCallbacks();
                removeAllCallbacks();
                mInputText.setVisibility(View.INVISIBLE);
                hideSoftInput();
                mLastDownOrMoveEventY = mLastDownEventY = event.getY();
                mLastDownOrMoveEventY = mLastDownEventY = event.getY();
                mLastDownEventTime = event.getEventTime();
                mLastDownEventTime = event.getEventTime();
                mIgnoreMoveEvents = false;
                mIgnoreMoveEvents = false;
@@ -883,11 +890,9 @@ public class NumberPicker extends LinearLayout {
                    mFlingScroller.forceFinished(true);
                    mFlingScroller.forceFinished(true);
                    mAdjustScroller.forceFinished(true);
                    mAdjustScroller.forceFinished(true);
                } else if (mLastDownEventY < mTopSelectionDividerTop) {
                } else if (mLastDownEventY < mTopSelectionDividerTop) {
                    hideSoftInput();
                    postChangeCurrentByOneFromLongPress(
                    postChangeCurrentByOneFromLongPress(
                            false, ViewConfiguration.getLongPressTimeout());
                            false, ViewConfiguration.getLongPressTimeout());
                } else if (mLastDownEventY > mBottomSelectionDividerBottom) {
                } else if (mLastDownEventY > mBottomSelectionDividerBottom) {
                    hideSoftInput();
                    postChangeCurrentByOneFromLongPress(
                    postChangeCurrentByOneFromLongPress(
                            true, ViewConfiguration.getLongPressTimeout());
                            true, ViewConfiguration.getLongPressTimeout());
                } else {
                } else {
@@ -1120,6 +1125,7 @@ public class NumberPicker extends LinearLayout {
    @Override
    @Override
    public void scrollBy(int x, int y) {
    public void scrollBy(int x, int y) {
        int[] selectorIndices = mSelectorIndices;
        int[] selectorIndices = mSelectorIndices;
        int startScrollOffset = mCurrentScrollOffset;
        if (!mWrapSelectorWheel && y > 0
        if (!mWrapSelectorWheel && y > 0
                && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
                && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
            mCurrentScrollOffset = mInitialScrollOffset;
            mCurrentScrollOffset = mInitialScrollOffset;
@@ -1147,6 +1153,9 @@ public class NumberPicker extends LinearLayout {
                mCurrentScrollOffset = mInitialScrollOffset;
                mCurrentScrollOffset = mInitialScrollOffset;
            }
            }
        }
        }
        if (startScrollOffset != mCurrentScrollOffset) {
            onScrollChanged(0, mCurrentScrollOffset, 0, startScrollOffset);
        }
    }
    }


    @Override
    @Override
@@ -1281,11 +1290,11 @@ public class NumberPicker extends LinearLayout {
        InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
        InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
        if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) {
        if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) {
            inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
            inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
        }
        if (mHasSelectorWheel) {
        if (mHasSelectorWheel) {
            mInputText.setVisibility(View.INVISIBLE);
            mInputText.setVisibility(View.INVISIBLE);
        }
        }
    }
    }
    }


    /**
    /**
     * Computes the max width if no such specified as an attribute.
     * Computes the max width if no such specified as an attribute.
@@ -1735,7 +1744,10 @@ public class NumberPicker extends LinearLayout {
        }
        }
        int previous = mValue;
        int previous = mValue;
        mValue = current;
        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();
            updateInputTextView();
        }
        if (notifyChange) {
        if (notifyChange) {
            notifyChange(previous, current);
            notifyChange(previous, current);
        }
        }
@@ -1752,7 +1764,7 @@ public class NumberPicker extends LinearLayout {
     */
     */
     private void changeValueByOne(boolean increment) {
     private void changeValueByOne(boolean increment) {
        if (mHasSelectorWheel) {
        if (mHasSelectorWheel) {
            mInputText.setVisibility(View.INVISIBLE);
            hideSoftInput();
            if (!moveToFinalScrollerPosition(mFlingScroller)) {
            if (!moveToFinalScrollerPosition(mFlingScroller)) {
                moveToFinalScrollerPosition(mAdjustScroller);
                moveToFinalScrollerPosition(mAdjustScroller);
            }
            }
@@ -1799,9 +1811,8 @@ public class NumberPicker extends LinearLayout {
     */
     */
    private void onScrollerFinished(Scroller scroller) {
    private void onScrollerFinished(Scroller scroller) {
        if (scroller == mFlingScroller) {
        if (scroller == mFlingScroller) {
            if (!ensureScrollWheelAdjusted()) {
            ensureScrollWheelAdjusted();
            updateInputTextView();
            updateInputTextView();
            }
            onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
        } else {
        } else {
            if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
            if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
@@ -1937,10 +1948,26 @@ public class NumberPicker extends LinearLayout {
         */
         */
        String text = (mDisplayedValues == null) ? formatNumber(mValue)
        String text = (mDisplayedValues == null) ? formatNumber(mValue)
                : mDisplayedValues[mValue - mMinValue];
                : 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);
                mInputText.setText(text);
                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                    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 true;
            }
            }
        }


        return false;
        return false;
    }
    }