@@ -9,6 +9,7 @@ import android.widget.ScrollView
99import com.facebook.react.views.scroll.ReactScrollView
1010import com.facebook.react.views.swiperefresh.ReactSwipeRefreshLayout
1111import com.facebook.react.views.textinput.ReactEditText
12+ import com.facebook.react.views.view.ReactViewGroup
1213import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
1314import com.swmansion.gesturehandler.react.isScreenReaderOn
1415
@@ -79,6 +80,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
7980 is ReactEditText -> this .hook = EditTextHook (this , view)
8081 is ReactSwipeRefreshLayout -> this .hook = SwipeRefreshLayoutHook (this , view)
8182 is ReactScrollView -> this .hook = ScrollViewHook ()
83+ is ReactViewGroup -> this .hook = ReactViewGroupHook ()
8284 }
8385 }
8486
@@ -99,7 +101,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
99101 if (state == STATE_UNDETERMINED && ! hook.canBegin(event)) {
100102 cancel()
101103 } else {
102- view.onTouchEvent( event)
104+ hook.sendTouchEvent(view, event)
103105 if ((state == STATE_UNDETERMINED || state == STATE_BEGAN ) && view.isPressed) {
104106 activate()
105107 }
@@ -116,12 +118,12 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
116118 when {
117119 shouldActivateOnStart -> {
118120 tryIntercept(view, event)
119- view.onTouchEvent( event)
121+ hook.sendTouchEvent(view, event)
120122 activate()
121123 }
122124
123125 tryIntercept(view, event) -> {
124- view.onTouchEvent( event)
126+ hook.sendTouchEvent(view, event)
125127 activate()
126128 }
127129
@@ -136,7 +138,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
136138 }
137139 }
138140 } else if (state == STATE_ACTIVE ) {
139- view.onTouchEvent( event)
141+ hook.sendTouchEvent(view, event)
140142 }
141143 }
142144
@@ -145,7 +147,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
145147 val event = MotionEvent .obtain(time, time, MotionEvent .ACTION_CANCEL , 0f , 0f , 0 ).apply {
146148 action = MotionEvent .ACTION_CANCEL
147149 }
148- view !! .onTouchEvent( event)
150+ hook.sendTouchEvent(view, event)
149151 event.recycle()
150152 }
151153
@@ -199,6 +201,11 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
199201 * by this one.
200202 */
201203 fun shouldCancelRootViewGestureHandlerIfNecessary () = false
204+
205+ /* *
206+ * Passes the event down to the underlying view using the correct method.
207+ */
208+ fun sendTouchEvent (view : View ? , event : MotionEvent ) = view?.onTouchEvent(event)
202209 }
203210
204211 private class EditTextHook (
@@ -278,4 +285,12 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
278285 private class ScrollViewHook : NativeViewGestureHandlerHook {
279286 override fun shouldCancelRootViewGestureHandlerIfNecessary () = true
280287 }
288+
289+ private class ReactViewGroupHook : NativeViewGestureHandlerHook {
290+ // There are cases where a native component is wrapped with a `ReactViewGroup` (the component is rendered
291+ // inside a `<View />` component in JS). In such cases, calling `onTouchEvent` wouldn't work as those are
292+ // ignored by the wrapper view. Instead `dispatchTouchEvent` can be used, which causes the view to dispatch
293+ // the event to its children.
294+ override fun sendTouchEvent (view : View ? , event : MotionEvent ) = view?.dispatchTouchEvent(event)
295+ }
281296}
0 commit comments