From 7cc29dc44da3826fc381a1e3ddfa4f4c1311e6db Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 10 Jun 2021 00:00:35 -0700 Subject: [PATCH] Fix RecyclerViewFastScroller bugs, hide keyboard Bug: 189982238 Bug: 187561242 Bug: 187909098 Test: manual Change-Id: I693810e5761004c48d028253c25a2fe96477af40 --- .../allapps/AllAppsRecyclerView.java | 4 +- .../views/RecyclerViewFastScroller.java | 39 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index d536c3afeb..5bbd02b5ed 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -190,8 +190,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView { case SCROLL_STATE_DRAGGING: mgr.logger().sendToInteractionJankMonitor( LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this); - hideKeyboardAsync(ActivityContext.lookupContext(getContext()), - getApplicationWindowToken()); break; case SCROLL_STATE_IDLE: mgr.logger().sendToInteractionJankMonitor( @@ -207,6 +205,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView { && mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) { mEmptySearchBackground.setHotspot(e.getX(), e.getY()); } + hideKeyboardAsync(ActivityContext.lookupContext(getContext()), + getApplicationWindowToken()); return result; } diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java index 9d0913ad25..e607ab3f7e 100644 --- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java +++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Insets; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; @@ -32,6 +33,7 @@ import android.util.Property; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.WindowInsets; import android.widget.TextView; import androidx.annotation.Nullable; @@ -51,6 +53,7 @@ import java.util.List; */ public class RecyclerViewFastScroller extends View { + private static final int FASTSCROLL_THRESHOLD_MILLIS = 200; private static final int SCROLL_DELTA_THRESHOLD_DP = 4; private static final Rect sTempRect = new Rect(); @@ -101,6 +104,7 @@ public class RecyclerViewFastScroller extends View { private final boolean mCanThumbDetach; private boolean mIgnoreDragGesture; private boolean mIsRecyclerViewFirstChildInParent = true; + private long mDownTimeStampMillis; // This is the offset from the top of the scrollbar when the user first starts touching. To // prevent jumping, this offset is applied as the user scrolls. @@ -112,6 +116,7 @@ public class RecyclerViewFastScroller extends View { private TextView mPopupView; private boolean mPopupVisible; private String mPopupSectionName; + private Insets mSystemGestureInsets; protected BaseRecyclerView mRv; private RecyclerView.OnScrollListener mOnScrollListener; @@ -237,6 +242,7 @@ public class RecyclerViewFastScroller extends View { // Keep track of the down positions mDownX = x; mDownY = mLastY = y; + mDownTimeStampMillis = ev.getDownTime(); if ((Math.abs(mDy) < mDeltaThreshold && mRv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) { @@ -246,22 +252,27 @@ public class RecyclerViewFastScroller extends View { } if (isNearThumb(x, y)) { mTouchOffsetY = mDownY - mThumbOffsetY; - } else if (mRv.supportsFastScrolling() - && isNearScrollBar(mDownX)) { - calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY); - updateFastScrollSectionNameAndThumbOffset(y); } break; case MotionEvent.ACTION_MOVE: mLastY = y; + int absDeltaY = Math.abs(y - mDownY); + int absDeltaX = Math.abs(x - mDownX); // Check if we should start scrolling, but ignore this fastscroll gesture if we have // exceeded some fixed movement - mIgnoreDragGesture |= Math.abs(y - mDownY) > mConfig.getScaledPagingTouchSlop(); - if (!mIsDragging && !mIgnoreDragGesture && mRv.supportsFastScrolling() && - isNearThumb(mDownX, mLastY) && - Math.abs(y - mDownY) > mConfig.getScaledTouchSlop()) { - calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY); + mIgnoreDragGesture |= absDeltaY > mConfig.getScaledPagingTouchSlop(); + + if (!mIsDragging && !mIgnoreDragGesture && mRv.supportsFastScrolling()) { + // condition #1: triggering thumb is distance, angle based + if ((isNearThumb(mDownX, mLastY) + && absDeltaY > mConfig.getScaledPagingTouchSlop() + && absDeltaY > absDeltaX) + // condition#2: Fastscroll function is now time based + || (isNearScrollBar(mDownX) && ev.getEventTime() - mDownTimeStampMillis + > FASTSCROLL_THRESHOLD_MILLIS)) { + calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY); + } } if (mIsDragging) { updateFastScrollSectionNameAndThumbOffset(y); @@ -328,12 +339,22 @@ public class RecyclerViewFastScroller extends View { canvas.drawRoundRect(mThumbBounds, r, r, mThumbPaint); if (Utilities.ATLEAST_Q) { mThumbBounds.roundOut(SYSTEM_GESTURE_EXCLUSION_RECT.get(0)); + // swiping very close to the thumb area (not just within it's bound) + // will also prevent back gesture SYSTEM_GESTURE_EXCLUSION_RECT.get(0).offset(mThumbDrawOffset.x, mThumbDrawOffset.y); + SYSTEM_GESTURE_EXCLUSION_RECT.get(0).left = SYSTEM_GESTURE_EXCLUSION_RECT.get(0).right + - mSystemGestureInsets.right; setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT); } canvas.restoreToCount(saveCount); } + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + mSystemGestureInsets = insets.getSystemGestureInsets(); + return super.onApplyWindowInsets(insets); + } + private float getScrollThumbRadius() { return mWidth + mThumbPadding + mThumbPadding; }