mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fixing nested horizontal scrollview scrolling on Android (#39097)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/39097 Changelog: [Internal][Added] - Created mechanism to have nested horizontal scrollviews (or flatlists/sectionlists) by prioritizing scrolling on deeper nested scrollviews which have the enableNestedScroll prop equal to true. Reviewed By: NickGerleman Differential Revision: D48504762 fbshipit-source-id: 1a6d01f68e142d99ea494e2b5630979c7be2ecce
This commit is contained in:
committed by
Facebook GitHub Bot
parent
08f0cda867
commit
211f3145db
+53
@@ -471,12 +471,65 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static HorizontalScrollView findDeepestScrollViewForMotionEvent(
|
||||
View view, MotionEvent ev) {
|
||||
return findDeepestScrollViewForMotionEvent(view, ev, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static HorizontalScrollView findDeepestScrollViewForMotionEvent(
|
||||
View view, MotionEvent ev, boolean skipInitialView) {
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Rect rectOnScreen = new Rect();
|
||||
view.getGlobalVisibleRect(rectOnScreen);
|
||||
if (!rectOnScreen.contains((int) ev.getRawX(), (int) ev.getRawY())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only consider the current view if it's not the initial view. We check the
|
||||
// current view first to bail out of recursion. Essentially if there's any
|
||||
// nested horizontal scrollview with nested scrolling enabled, the parent
|
||||
// scroll view shouldn't pick up the down event.
|
||||
if (!skipInitialView
|
||||
&& view instanceof HorizontalScrollView
|
||||
&& ViewCompat.isNestedScrollingEnabled(view)
|
||||
&& (view instanceof ReactHorizontalScrollView
|
||||
&& ((ReactHorizontalScrollView) view).mScrollEnabled)) {
|
||||
return (HorizontalScrollView) view;
|
||||
}
|
||||
|
||||
// First, check child views recursively before considering this view.
|
||||
if (view instanceof ViewGroup) {
|
||||
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
|
||||
HorizontalScrollView foundScrollView =
|
||||
findDeepestScrollViewForMotionEvent(((ViewGroup) view).getChildAt(i), ev, false);
|
||||
|
||||
if (foundScrollView != null) {
|
||||
// If a deeper HorizontalScrollView is found in child views, return it.
|
||||
return foundScrollView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return null if no matching view is found.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (!mScrollEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ev.getAction() == MotionEvent.ACTION_DOWN)
|
||||
&& findDeepestScrollViewForMotionEvent(this, ev) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We intercept the touch event if the children are not supposed to receive it.
|
||||
if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user