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

Commit b6545c44 authored by Peter_Liang's avatar Peter_Liang
Browse files

Fix the jelly effect when scrolling the a11y floating menu.

Root cause:
The default scroll mode of RecyclerView is scrollable.

Solution:
Set OVER_SCROLL_ALWAYS when the actual height of target list exceed the
available height, otherwise OVER_SCROLL_NEVER.

Bug: 184817161
Test: atest AccessibilityFloatingMenuViewTest
Change-Id: I9a2bfd674141475e5546b1ed5450e65132ffd384
parent 463493f5
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -371,6 +371,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        mAdapter.notifyDataSetChanged();

        updateRadiusWith(mSizeType, mRadiusType, mTargets.size());
        updateScrollModeWith(hasExceededMaxLayoutHeight());
        setSystemGestureExclusion();

        fadeOut();
@@ -614,6 +615,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        updateColor();
        updateStrokeWith(newConfig.uiMode, mAlignment);
        updateLocationWith(mAlignment, mPercentageY);
        updateScrollModeWith(hasExceededMaxLayoutHeight());
    }

    @VisibleForTesting
@@ -679,6 +681,12 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        mListView.setLayoutParams(layoutParams);
    }

    private void updateScrollModeWith(boolean hasExceededMaxLayoutHeight) {
        mListView.setOverScrollMode(hasExceededMaxLayoutHeight
                ? OVER_SCROLL_ALWAYS
                : OVER_SCROLL_NEVER);
    }

    private void updateColor() {
        final int menuColorResId = R.color.accessibility_floating_menu_background;
        getMenuGradientDrawable().setColor(getResources().getColor(menuColorResId));
@@ -726,6 +734,11 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        layerDrawable.setLayerInset(INDEX_MENU_ITEM, left, 0, right, 0);
    }

    @VisibleForTesting
    boolean hasExceededMaxLayoutHeight() {
        return calculateActualLayoutHeight() > getMaxLayoutHeight();
    }

    @Alignment
    private int calculateCurrentAlignment() {
        return mCurrentLayoutParams.x >= ((MIN_WINDOW_X + getMaxWindowX()) / 2)
@@ -737,6 +750,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        return mCurrentLayoutParams.y / (float) getMaxWindowY();
    }

    private int calculateActualLayoutHeight() {
        return (mPadding + mIconHeight) * mTargets.size() + mPadding;
    }

    private @DimenRes int getRadiusResId(@SizeType int sizeType, int itemCount) {
        return sizeType == SizeType.SMALL
                ? getSmallSizeResIdWith(itemCount)
@@ -760,13 +777,16 @@ public class AccessibilityFloatingMenuView extends FrameLayout
        return new Rect(0, 0, mScreenWidth - getWindowWidth(), mScreenHeight - getWindowHeight());
    }

    private int getMaxLayoutHeight() {
        return mScreenHeight - mMargin * 2;
    }

    private int getLayoutWidth() {
        return mPadding * 2 + mIconWidth;
    }

    private int getLayoutHeight() {
        return Math.min(mScreenHeight - mMargin * 2,
                (mPadding + mIconHeight) * mTargets.size() + mPadding);
        return Math.min(getMaxLayoutHeight(), calculateActualLayoutHeight());
    }

    private int getWindowWidth() {
+27 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.accessibility.floatingmenu;

import static android.view.View.OVER_SCROLL_ALWAYS;
import static android.view.View.OVER_SCROLL_NEVER;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
@@ -437,6 +440,30 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
                action -> action.getId() == R.id.action_move_to_edge_and_hide)).isTrue();
    }

    @Test
    public void onTargetsChanged_exceedAvailableHeight_overScrollAlways() {
        final RecyclerView listView = new RecyclerView(mContext);
        final AccessibilityFloatingMenuView menuView =
                spy(new AccessibilityFloatingMenuView(mContext, listView));
        doReturn(true).when(menuView).hasExceededMaxLayoutHeight();

        menuView.onTargetsChanged(mTargets);

        assertThat(listView.getOverScrollMode()).isEqualTo(OVER_SCROLL_ALWAYS);
    }

    @Test
    public void onTargetsChanged_notExceedAvailableHeight_overScrollNever() {
        final RecyclerView listView = new RecyclerView(mContext);
        final AccessibilityFloatingMenuView menuView =
                spy(new AccessibilityFloatingMenuView(mContext, listView));
        doReturn(false).when(menuView).hasExceededMaxLayoutHeight();

        mMenuView.onTargetsChanged(mTargets);

        assertThat(mListView.getOverScrollMode()).isEqualTo(OVER_SCROLL_NEVER);
    }

    @After
    public void tearDown() {
        mInterceptMotionEvent = null;