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 cdfd8d1416..30ba4fcf7e 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 @@ -595,6 +595,16 @@ open class GestureHandler { // generated faster than they can be treated by JS thread eventCoalescingKey = nextEventCoalescingKey++ } + + check(hostDetectorView != null || orchestrator != null) { + "Manually handled gesture had not been assigned to any detector" + } + + if (orchestrator == null) { + // If the state is set manually, the handler may not have been fully recorded by the orchestrator. + hostDetectorView?.recordHandlerIfNotPresent(this) + } + orchestrator!!.onHandlerStateChange(this, newState, oldState) onStateChange(newState, oldState) } 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 3f13f15b82..5907cd6ac1 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 @@ -442,7 +442,7 @@ class GestureHandlerOrchestrator( } } - private fun recordHandlerIfNotPresent(handler: GestureHandler, view: View) { + fun recordHandlerIfNotPresent(handler: GestureHandler, view: View?) { if (gestureHandlers.contains(handler)) { return } 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 32cb973b80..c4ad8da6e1 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 @@ -21,7 +21,6 @@ import android.view.MotionEvent import android.view.View import android.view.View.OnClickListener import android.view.ViewGroup -import android.view.ViewParent import android.view.accessibility.AccessibilityNodeInfo import androidx.core.view.children import com.facebook.react.R @@ -497,9 +496,9 @@ class RNGestureHandlerButtonViewManager : // a parent button from playing) return if (!isChildTouched()) { if (context.isScreenReaderOn()) { - findGestureHandlerRootView()?.activateNativeHandlers(this) + RNGestureHandlerRootView.findGestureHandlerRootView(this)?.activateNativeHandlers(this) } else if (receivedKeyEvent) { - findGestureHandlerRootView()?.activateNativeHandlers(this) + RNGestureHandlerRootView.findGestureHandlerRootView(this)?.activateNativeHandlers(this) receivedKeyEvent = false } @@ -538,20 +537,6 @@ class RNGestureHandlerButtonViewManager : // by default Viewgroup would pass hotspot change events } - private fun findGestureHandlerRootView(): RNGestureHandlerRootView? { - var parent: ViewParent? = this.parent - var gestureHandlerRootView: RNGestureHandlerRootView? = null - - while (parent != null) { - if (parent is RNGestureHandlerRootView) { - gestureHandlerRootView = parent - } - parent = parent.parent - } - - return gestureHandlerRootView - } - companion object { var resolveOutValue = TypedValue() var touchResponder: ButtonViewGroup? = null diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt index c57dd8ad37..f90e4f1c7e 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt @@ -9,6 +9,7 @@ import com.facebook.react.uimanager.events.Event import com.facebook.react.views.swiperefresh.ReactSwipeRefreshLayout import com.facebook.react.views.view.ReactViewGroup import com.swmansion.gesturehandler.core.GestureHandler +import com.swmansion.gesturehandler.react.RNGestureHandlerRootView class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) { private val reactContext: ThemedReactContext @@ -203,6 +204,10 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) { } } + fun recordHandlerIfNotPresent(handler: GestureHandler) { + RNGestureHandlerRootView.findGestureHandlerRootView(this)?.recordHandlerIfNotPresent(handler) + } + private fun ReadableArray.mapVirtualChildren(): List = List(size()) { i -> val child = getMap(i) ?: return@List null val handlerTags = child.getArray("handlerTags")?.toIntList().orEmpty() diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt index 131119ecb7..fb327172be 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt @@ -141,6 +141,10 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView: orchestrator?.activateNativeHandlersForView(view) } + fun recordHandlerIfNotPresent(handler: GestureHandler) { + orchestrator?.recordHandlerIfNotPresent(handler, null) + } + companion object { private const val MIN_ALPHA_FOR_TOUCH = 0.1f private fun findRootViewTag(viewGroup: ViewGroup): ViewGroup { diff --git a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt index f66bcd8387..79167e9c27 100644 --- a/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +++ b/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt @@ -5,11 +5,13 @@ import android.util.Log import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import android.view.ViewParent import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.UiThreadUtil import com.facebook.react.common.ReactConstants import com.facebook.react.uimanager.RootView import com.facebook.react.views.view.ReactViewGroup +import com.swmansion.gesturehandler.core.GestureHandler class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) { private var moduleId: Int = -1 @@ -39,6 +41,10 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) { rootHelper?.tearDown() } + fun recordHandlerIfNotPresent(handler: GestureHandler) { + rootHelper?.recordHandlerIfNotPresent(handler) + } + override fun dispatchTouchEvent(event: MotionEvent) = if (rootViewEnabled && rootHelper!!.dispatchTouchEvent(event)) { true } else { @@ -87,5 +93,19 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) { } return false } + + fun findGestureHandlerRootView(viewGroup: ViewGroup): RNGestureHandlerRootView? { + var parent: ViewParent? = viewGroup.parent + var gestureHandlerRootView: RNGestureHandlerRootView? = null + + while (parent != null) { + if (parent is RNGestureHandlerRootView) { + gestureHandlerRootView = parent + } + parent = parent.parent + } + + return gestureHandlerRootView + } } }