From 87ad1e857096393fcb7b4b086a117d08e1c4f7d5 Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Fri, 4 Mar 2022 15:50:00 -0800 Subject: [PATCH] Intercept touch event for simulated joystick scrolling to avoid nested scroll view issues Summary: The issue to be fixed here is an edge case when in nested scroll view, for example vertical scroll wraps horizontal scroll, when user scrolls horizontally then move the joystick downwards, the horizontal scroll would bounce back. This is shown in the demo: https://pxl.cl/209f8 The root cause of the issue is due to two workflows fight to set the scroll position and confusing the scroll change dispatcher to calculate fling velocity direction, which caused a wrong fling behavior. Check this log and description to get more details: {F706620839} To fix the issue, in this diff we overridden the `onInterceptTouchEvent` method in panel app scroll views, and make it return true when the previous scroll is still running. This effectively skips the drag slop in the default scroll view behavior, as we know the touch event should've been handled by the scroll view if it's still scrolling. This way, the vertical scroll part on the vertical scroll view will not be dispatched to the horizontal scroll at all. This allows the nested scroll view to work separately. Changelog: [Android][Internal] - Share the post intercept touch event logic in scroll views Reviewed By: javache Differential Revision: D34627329 fbshipit-source-id: d500ec3bfbe349a45ef5c1360b5c8807c168f682 --- .../views/scroll/ReactHorizontalScrollView.java | 14 +++++++++----- .../react/views/scroll/ReactScrollView.java | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 1317c6e43de..006feb2ffac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -460,11 +460,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView try { if (super.onInterceptTouchEvent(ev)) { - NativeGestureUtil.notifyNativeGestureStarted(this, ev); - ReactScrollViewHelper.emitScrollBeginDragEvent(this); - mDragging = true; - enableFpsListener(); - getFlingAnimator().cancel(); + handleInterceptedTouchEvent(ev); return true; } } catch (IllegalArgumentException e) { @@ -477,6 +473,14 @@ public class ReactHorizontalScrollView extends HorizontalScrollView return false; } + protected void handleInterceptedTouchEvent(MotionEvent ev) { + NativeGestureUtil.notifyNativeGestureStarted(this, ev); + ReactScrollViewHelper.emitScrollBeginDragEvent(this); + mDragging = true; + enableFpsListener(); + getFlingAnimator().cancel(); + } + @Override public boolean pageScroll(int direction) { boolean handled = super.pageScroll(direction); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 3fbfb7a4d52..32261eb3dc9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -340,11 +340,7 @@ public class ReactScrollView extends ScrollView try { if (super.onInterceptTouchEvent(ev)) { - NativeGestureUtil.notifyNativeGestureStarted(this, ev); - ReactScrollViewHelper.emitScrollBeginDragEvent(this); - mDragging = true; - enableFpsListener(); - getFlingAnimator().cancel(); + handleInterceptedTouchEvent(ev); return true; } } catch (IllegalArgumentException e) { @@ -357,6 +353,14 @@ public class ReactScrollView extends ScrollView return false; } + protected void handleInterceptedTouchEvent(MotionEvent ev) { + NativeGestureUtil.notifyNativeGestureStarted(this, ev); + ReactScrollViewHelper.emitScrollBeginDragEvent(this); + mDragging = true; + enableFpsListener(); + getFlingAnimator().cancel(); + } + @Override public boolean onTouchEvent(MotionEvent ev) { if (!mScrollEnabled) {