Skip to content

Commit 3c9f4bc

Browse files
committed
[Android] Properly handle requestDisallowInterceptTouchEvent for v3
1 parent bd8e57a commit 3c9f4bc

5 files changed

Lines changed: 77 additions & 15 deletions

File tree

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,30 @@ class GestureHandlerOrchestrator(
358358
event.recycle()
359359
}
360360

361+
/**
362+
* Cancels all handlers created using API v1 and v2
363+
*/
364+
fun cancelAllLegacyHandlers() {
365+
val handlersToProcess = obtainHandlerList()
366+
handlersToProcess.addAll(gestureHandlers)
367+
368+
try {
369+
handlersToProcess.forEach {
370+
if (it.actionType == GestureHandler.ACTION_TYPE_JS_FUNCTION_OLD_API ||
371+
it.actionType == GestureHandler.ACTION_TYPE_JS_FUNCTION_NEW_API ||
372+
it.actionType == GestureHandler.ACTION_TYPE_REANIMATED_WORKLET ||
373+
it.actionType == GestureHandler.ACTION_TYPE_NATIVE_ANIMATED_EVENT
374+
) {
375+
it.cancel()
376+
}
377+
}
378+
379+
scheduleFinishedHandlersCleanup()
380+
} finally {
381+
recycleHandlerList(handlersToProcess)
382+
}
383+
}
384+
361385
/**
362386
* isViewAttachedUnderWrapper checks whether all of parents for view related to handler
363387
* view are attached. Since there might be an issue rarely observed when view

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,24 @@ class RNGestureHandlerButtonViewManager :
783783
}
784784
}
785785

786+
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
787+
super.requestDisallowInterceptTouchEvent(disallowIntercept)
788+
if (!disallowIntercept) {
789+
return
790+
}
791+
792+
val moduleId = moduleId ?: return
793+
val managedHandlerTag = managedHandlerTag ?: return
794+
795+
val orchestrator =
796+
RNGestureHandlerRootView.findGestureHandlerRootView(this)?.orchestrator ?: return
797+
val handler = RNGestureHandlerModule.registries[moduleId]?.getHandler(managedHandlerTag) ?: return
798+
799+
if (!orchestrator.isHandlingTouch && handler.view != null) {
800+
handler.cancel()
801+
}
802+
}
803+
786804
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
787805
if (super.onInterceptTouchEvent(event)) {
788806
return true

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
4646
super.onDetachedFromWindow()
4747
}
4848

49+
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
50+
super.requestDisallowInterceptTouchEvent(disallowIntercept)
51+
if (!disallowIntercept) {
52+
return
53+
}
54+
55+
56+
val orchestrator = RNGestureHandlerRootView.findGestureHandlerRootView(this)?.orchestrator ?: return
57+
58+
if (!orchestrator.isHandlingTouch) {
59+
val currentHandlers = attachedHandlers.mapNotNull { tag ->
60+
RNGestureHandlerModule.registries[this.moduleId]?.getHandler(tag)
61+
}.filter {
62+
// The handler has been recorded
63+
it.view != null
64+
}
65+
66+
currentHandlers.forEach {
67+
it.cancel()
68+
}
69+
}
70+
}
71+
4972
fun setModuleId(id: Int) {
5073
if (this.moduleId == id) {
5174
return

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import com.swmansion.gesturehandler.core.GestureHandlerOrchestrator
1616
import com.swmansion.gesturehandler.core.OnJSResponderCancelListener
1717

1818
class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView: ViewGroup, private val moduleId: Int) {
19-
private val orchestrator: GestureHandlerOrchestrator?
19+
val orchestrator: GestureHandlerOrchestrator?
2020
private val jsGestureHandler: GestureHandler?
2121
val rootView: ViewGroup
2222
private var shouldIntercept = false
@@ -57,7 +57,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
5757
}
5858
jsGestureHandler = RootViewGestureHandler(handlerTag = -wrappedViewTag)
5959
registry.registerHandler(jsGestureHandler)
60-
registry.attachHandlerToView(jsGestureHandler.tag, wrappedViewTag, GestureHandler.ACTION_TYPE_JS_FUNCTION_OLD_API)
60+
registry.attachHandlerToView(jsGestureHandler.tag, wrappedViewTag, GestureHandler.ACTION_TYPE_NONE)
6161
module.registerRootHelper(this)
6262
}
6363

@@ -120,7 +120,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
120120
if (orchestrator != null && !passingTouch) {
121121
// if we are in the process of delivering touch events via GH orchestrator, we don't want to
122122
// treat it as a native gesture capturing the lock
123-
tryCancelAllHandlers()
123+
orchestrator.cancelAllLegacyHandlers()
124124
}
125125
}
126126

@@ -142,17 +142,6 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
142142
return shouldIntercept
143143
}
144144

145-
private fun tryCancelAllHandlers() {
146-
// In order to cancel handlers we activate handler that is hooked to the root view
147-
jsGestureHandler?.apply {
148-
if (state == GestureHandler.STATE_BEGAN) {
149-
// Try activate main JS handler
150-
activate()
151-
end()
152-
}
153-
}
154-
}
155-
156145
fun activateNativeHandlers(view: View) {
157146
orchestrator?.activateNativeHandlersForView(view)
158147
}

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ import com.facebook.react.common.ReactConstants
1212
import com.facebook.react.uimanager.RootView
1313
import com.facebook.react.views.view.ReactViewGroup
1414
import com.swmansion.gesturehandler.core.GestureHandler
15+
import com.swmansion.gesturehandler.core.GestureHandlerOrchestrator
1516

1617
class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
1718
private var moduleId: Int = -1
1819
private var rootViewEnabled = false
1920
private var unstableForceActive = false
2021
private var rootHelper: RNGestureHandlerRootHelper? = null // TODO: resettable lateinit
2122

23+
val orchestrator: GestureHandlerOrchestrator?
24+
get() = rootHelper?.orchestrator
25+
2226
override fun onAttachedToWindow() {
2327
super.onAttachedToWindow()
2428
rootViewEnabled = unstableForceActive || !hasGestureHandlerEnabledRootView(this)
@@ -72,7 +76,7 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
7276
}
7377

7478
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
75-
if (rootViewEnabled) {
79+
if (rootViewEnabled && disallowIntercept) {
7680
rootHelper!!.requestDisallowInterceptTouchEvent()
7781
}
7882
super.requestDisallowInterceptTouchEvent(disallowIntercept)
@@ -114,6 +118,10 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
114118
while (parent != null) {
115119
if (parent is RNGestureHandlerRootView) {
116120
gestureHandlerRootView = parent
121+
122+
if (parent.rootViewEnabled) {
123+
return parent
124+
}
117125
}
118126
parent = parent.parent
119127
}

0 commit comments

Comments
 (0)