From e88a5e763ca03886b374d97e52b1e60626c42789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 12 Oct 2026 16:38:45 +0200 Subject: [PATCH] [Android] Reset the native DOWN flag for unmanaged buttons --- .../react/RNGestureHandlerButtonViewManager.kt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt index 72c815ce49..8356f01035 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt @@ -762,6 +762,17 @@ class RNGestureHandlerButtonViewManager : } override fun onHandlerStateChange(handler: NativeViewGestureHandler, newState: Int, prevState: Int) { + if (newState == GestureHandler.STATE_BEGAN) { + // Reset here, not on gesture end: the native DOWN sets the flag even when the orchestrator + // never tracks the handler (disabled button, alpha below the traversal threshold), so a + // terminal state may never come and the stale value would survive. BEGAN precedes both the + // native dispatch of the same DOWN and the sweep that reads the flag. + // + // Runs before the managed guard because the sweep reads the flag for detector-attached + // buttons too, and those manage no handler. + receivedNativeDown = false + } + if (managedHandlerTag == null) { return } @@ -771,11 +782,6 @@ class RNGestureHandlerButtonViewManager : val localLastEventWasInside = lastEventWasInside if (newState == GestureHandler.STATE_BEGAN) { - // Reset here, not on gesture end: the native DOWN sets the flag even when the orchestrator - // never tracks the handler (disabled button, alpha below the traversal threshold), so a - // terminal state may never come and the stale value would survive. BEGAN precedes both the - // native dispatch of the same DOWN and the sweep that reads the flag. - receivedNativeDown = false flushPendingPressOut() pressDownTime = SystemClock.uptimeMillis() pressStarted = false