[Android] Fix taps triggering while swiping (#7459)
* [Android] Fix taps triggering while swiping
* Revert "[Android] Try to disambiguate taps from swipes (#7448)"
This reverts commit 96054f4add.
* Update patch to match callstack/react-native-pager-view#961
* Make it symmetrical
---------
Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
diff --git a/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class b/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..b64fccc
|
||||||
|
Binary files /dev/null and b/node_modules/react-native-pager-view/android/build/tmp/kotlin-classes/debug/com/reactnativepagerview/NestedScrollableHost.class differ
|
||||||
|
diff --git a/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt b/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
|
||||||
|
index 91d9946..87b58d0 100644
|
||||||
|
--- a/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
|
||||||
|
+++ b/node_modules/react-native-pager-view/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt
|
||||||
|
@@ -8,6 +8,7 @@ import android.view.ViewConfiguration
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
|
||||||
|
+import com.facebook.react.uimanager.events.NativeGestureUtil
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
|
@@ -27,6 +28,7 @@ class NestedScrollableHost : FrameLayout {
|
||||||
|
private var touchSlop = 0
|
||||||
|
private var initialX = 0f
|
||||||
|
private var initialY = 0f
|
||||||
|
+ private var nativeGestureStarted: Boolean = false
|
||||||
|
private val parentViewPager: ViewPager2?
|
||||||
|
get() {
|
||||||
|
var v: View? = parent as? View
|
||||||
|
@@ -57,17 +59,14 @@ class NestedScrollableHost : FrameLayout {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleInterceptTouchEvent(e: MotionEvent) {
|
||||||
|
- val orientation = parentViewPager?.orientation ?: return
|
||||||
|
-
|
||||||
|
- // Early return if child can't scroll in same direction as parent
|
||||||
|
- if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
|
||||||
|
- return
|
||||||
|
- }
|
||||||
|
+ val orientation = parentViewPager?.orientation
|
||||||
|
|
||||||
|
if (e.action == MotionEvent.ACTION_DOWN) {
|
||||||
|
initialX = e.x
|
||||||
|
initialY = e.y
|
||||||
|
- parent.requestDisallowInterceptTouchEvent(true)
|
||||||
|
+ if (orientation != null) {
|
||||||
|
+ parent.requestDisallowInterceptTouchEvent(true)
|
||||||
|
+ }
|
||||||
|
} else if (e.action == MotionEvent.ACTION_MOVE) {
|
||||||
|
val dx = e.x - initialX
|
||||||
|
val dy = e.y - initialY
|
||||||
|
@@ -78,6 +77,10 @@ class NestedScrollableHost : FrameLayout {
|
||||||
|
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
|
||||||
|
|
||||||
|
if (scaledDx > touchSlop || scaledDy > touchSlop) {
|
||||||
|
+ NativeGestureUtil.notifyNativeGestureStarted(this, e)
|
||||||
|
+ nativeGestureStarted = true
|
||||||
|
+
|
||||||
|
+ if (orientation == null) return
|
||||||
|
if (isVpHorizontal == (scaledDy > scaledDx)) {
|
||||||
|
// Gesture is perpendicular, allow all parents to intercept
|
||||||
|
parent.requestDisallowInterceptTouchEvent(false)
|
||||||
|
@@ -94,4 +97,14 @@ class NestedScrollableHost : FrameLayout {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ override fun onTouchEvent(e: MotionEvent): Boolean {
|
||||||
|
+ if (e.actionMasked == MotionEvent.ACTION_UP) {
|
||||||
|
+ if (nativeGestureStarted) {
|
||||||
|
+ NativeGestureUtil.notifyNativeGestureEnded(this, e)
|
||||||
|
+ nativeGestureStarted = false
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return super.onTouchEvent(e)
|
||||||
|
+ }
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {Children, forwardRef, useCallback, useContext} from 'react'
|
import React, {forwardRef, useCallback, useContext} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {DrawerGestureContext} from 'react-native-drawer-layout'
|
import {DrawerGestureContext} from 'react-native-drawer-layout'
|
||||||
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
|
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
|
||||||
@@ -17,7 +17,6 @@ import Animated, {
|
|||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
import {isAndroid} from '#/platform/detection'
|
|
||||||
import {useSetDrawerSwipeDisabled} from '#/state/shell'
|
import {useSetDrawerSwipeDisabled} from '#/state/shell'
|
||||||
import {atoms as a, native} from '#/alf'
|
import {atoms as a, native} from '#/alf'
|
||||||
|
|
||||||
@@ -149,11 +148,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
style={[a.flex_1]}
|
style={[a.flex_1]}
|
||||||
initialPage={initialPage}
|
initialPage={initialPage}
|
||||||
onPageScroll={handlePageScroll}>
|
onPageScroll={handlePageScroll}>
|
||||||
{isAndroid
|
{children}
|
||||||
? Children.map(children, child => (
|
|
||||||
<CaptureSwipesAndroid>{child}</CaptureSwipesAndroid>
|
|
||||||
))
|
|
||||||
: children}
|
|
||||||
</AnimatedPagerView>
|
</AnimatedPagerView>
|
||||||
</GestureDetector>
|
</GestureDetector>
|
||||||
</View>
|
</View>
|
||||||
@@ -161,39 +156,6 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// HACK.
|
|
||||||
// This works around https://github.com/callstack/react-native-pager-view/issues/960.
|
|
||||||
// It appears that the Pressables inside the pager get confused if there's enough work
|
|
||||||
// happening on the JS thread, and mistakingly interpret a pager swipe as a tap.
|
|
||||||
// We can prevent this by stealing all horizontal movements from the tree inside.
|
|
||||||
function CaptureSwipesAndroid({children}: {children: React.ReactNode}) {
|
|
||||||
const lastTouchStart = React.useRef<{x: number; y: number} | null>(null)
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
onTouchStart={e => {
|
|
||||||
lastTouchStart.current = {
|
|
||||||
x: e.nativeEvent.pageX,
|
|
||||||
y: e.nativeEvent.pageY,
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onMoveShouldSetResponderCapture={e => {
|
|
||||||
const coords = lastTouchStart.current
|
|
||||||
if (!coords) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const dx = Math.abs(e.nativeEvent.pageX - coords.x)
|
|
||||||
if (dx > 0) {
|
|
||||||
// This is a horizontal movement and will result in a swipe.
|
|
||||||
// Prevent pager children from receiving this touch.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}}>
|
|
||||||
{children}
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function usePagerHandlers(
|
function usePagerHandlers(
|
||||||
handlers: {
|
handlers: {
|
||||||
onPageScroll: (e: PagerViewOnPageScrollEventData) => void
|
onPageScroll: (e: PagerViewOnPageScrollEventData) => void
|
||||||
|
|||||||
Reference in New Issue
Block a user