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
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user