diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt index 980ff0d3e4..2f1a12b83a 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt @@ -609,10 +609,14 @@ open class GestureHandler { } // if there are tracked pointers and the gesture is about to end, send event cancelling all pointers - if (trackedPointersCount > 0 && - (newState == STATE_END || newState == STATE_CANCELLED || newState == STATE_FAILED) - ) { + if (trackedPointersCount > 0 && isFinished(newState)) { cancelPointers() + + // `cancelPointers` dispatches the event synchronously and its callback may change the state + // (e.g. via `GestureStateManager.fail`), in which case the transition is already complete. + if (isFinished(state)) { + return + } } val oldState = state @@ -998,6 +1002,8 @@ open class GestureHandler { } companion object { + fun isFinished(state: Int) = state == STATE_CANCELLED || state == STATE_FAILED || state == STATE_END + private const val DEFAULT_NEEDS_POINTER_DATA = false private const val DEFAULT_MANUAL_ACTIVATION = false private const val DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE = false diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt index 2e1f7c23e3..577979aa04 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt @@ -101,7 +101,7 @@ class GestureHandlerOrchestrator( private fun cleanupFinishedHandlers() { for (handler in gestureHandlers.asReversed()) { - if (isFinished(handler.state) && !handler.isAwaiting) { + if (GestureHandler.isFinished(handler.state) && !handler.isAwaiting) { handler.reset() handler.apply { isActive = false @@ -111,13 +111,13 @@ class GestureHandlerOrchestrator( } } - gestureHandlers.removeAll { isFinished(it.state) && !it.isAwaiting } + gestureHandlers.removeAll { GestureHandler.isFinished(it.state) && !it.isAwaiting } finishedHandlersCleanupScheduled = false } private fun hasOtherHandlerToWaitFor(handler: GestureHandler) = - gestureHandlers.any { !isFinished(it.state) && shouldHandlerWaitForOther(handler, it) } + gestureHandlers.any { !GestureHandler.isFinished(it.state) && shouldHandlerWaitForOther(handler, it) } private fun shouldBeCancelledByFinishedHandler(handler: GestureHandler) = gestureHandlers.any { shouldHandlerWaitForOther(handler, it) && it.state == GestureHandler.STATE_END } @@ -167,7 +167,7 @@ class GestureHandlerOrchestrator( handler.isAwaiting = false } - if (isFinished(newState)) { + if (GestureHandler.isFinished(newState)) { // We have to loop through copy in order to avoid modifying collection // while iterating over its elements val currentlyAwaitingHandlers = awaitingHandlers.toList() @@ -1027,9 +1027,5 @@ class GestureHandlerOrchestrator( true } } - - private fun isFinished(state: Int) = state == GestureHandler.STATE_CANCELLED || - state == GestureHandler.STATE_FAILED || - state == GestureHandler.STATE_END } }