From 3ffacb3735db676aa5dbd89f67b73942da888a7e Mon Sep 17 00:00:00 2001 From: osdnk Date: Thu, 30 Jan 2020 01:20:35 +0100 Subject: [PATCH 1/8] initial work --- Example/draggable/index.js | 27 ++++++++++++++----- .../react/views/modal/RNGHModalUtils.java | 17 ++++++++++++ .../react/RNGestureHandlerModule.java | 9 ++++--- .../react/RNGestureHandlerRootHelper.java | 17 +++++++----- 4 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java diff --git a/Example/draggable/index.js b/Example/draggable/index.js index 32b3b6f2c7..89bf100d2d 100644 --- a/Example/draggable/index.js +++ b/Example/draggable/index.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Animated, StyleSheet, View } from 'react-native'; +import { Animated, Modal, StyleSheet, View } from 'react-native'; import { PanGestureHandler, @@ -9,6 +9,7 @@ import { import { USE_NATIVE_DRIVER } from '../config'; import { LoremIpsum } from '../common'; +import gestureHandlerRootHOC from '../../gestureHandlerRootHOC'; export class DraggableBox extends Component { constructor(props) { @@ -61,14 +62,26 @@ export class DraggableBox extends Component { } } -export default class Example extends Component { +const ExampleWithHoc = gestureHandlerRootHOC( + class Example extends Component { + render() { + return ( + + + + + + ); + } + } +); + +export default class WrappedExample extends React.Component { render() { return ( - - - - - + + + ); } } diff --git a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java new file mode 100644 index 0000000000..29e5fea99b --- /dev/null +++ b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java @@ -0,0 +1,17 @@ +package com.facebook.react.views.modal; + + +import android.view.MotionEvent; +import android.view.ViewGroup; +import android.view.ViewParent; + +public class RNGHModalUtils { + static public void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { + ((ReactModalHostView.DialogRootViewGroup) modal).onChildStartedNativeGesture(androidEvent); + } + + static public boolean isDialogRootViewGroup(ViewParent modal) { + return modal instanceof ReactModalHostView.DialogRootViewGroup; + } + +} diff --git a/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.java b/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.java index 10f775c88f..c8565c3ea6 100644 --- a/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.java +++ b/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.java @@ -3,6 +3,7 @@ import android.content.Context; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import com.facebook.react.ReactRootView; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; @@ -555,7 +556,7 @@ public void onCatalystInstanceDestroy() { while (!mRoots.isEmpty()) { int sizeBefore = mRoots.size(); RNGestureHandlerRootHelper root = mRoots.get(0); - ReactRootView reactRootView = root.getRootView(); + ViewGroup reactRootView = root.getRootView(); if (reactRootView instanceof RNGestureHandlerEnabledRootView) { ((RNGestureHandlerEnabledRootView) reactRootView).tearDown(); } else { @@ -579,7 +580,8 @@ private void tryInitializeHandlerForReactRootView(int ancestorViewTag) { synchronized (mRoots) { for (int i = 0; i < mRoots.size(); i++) { RNGestureHandlerRootHelper root = mRoots.get(i); - if (root.getRootView().getRootViewTag() == rootViewTag) { + ViewGroup rootView = root.getRootView(); + if (rootView instanceof ReactRootView && ((ReactRootView) rootView).getRootViewTag() == rootViewTag) { // we have found root helper registered for a given react root, we don't need to // initialize a new one then return; @@ -638,7 +640,8 @@ public void unregisterRootHelper(RNGestureHandlerRootHelper root) { synchronized (mRoots) { for (int i = 0; i < mRoots.size(); i++) { RNGestureHandlerRootHelper root = mRoots.get(i); - if (root.getRootView().getRootViewTag() == rootViewTag) { + ViewGroup rootView = root.getRootView(); + if (rootView instanceof ReactRootView && ((ReactRootView) rootView).getRootViewTag() == rootViewTag) { return root; } } diff --git a/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.java b/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.java index 490f412e13..fcfc2f874f 100644 --- a/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.java +++ b/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.java @@ -10,6 +10,7 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.common.ReactConstants; +import com.facebook.react.views.modal.RNGHModalUtils; import com.swmansion.gesturehandler.GestureHandler; import com.swmansion.gesturehandler.GestureHandlerOrchestrator; @@ -20,22 +21,22 @@ public class RNGestureHandlerRootHelper { private final ReactContext mContext; private final GestureHandlerOrchestrator mOrchestrator; private final GestureHandler mJSGestureHandler; - private final ReactRootView mReactRootView; + private final ViewGroup mReactRootView; private boolean mShouldIntercept = false; private boolean mPassingTouch = false; - private static ReactRootView findRootViewTag(ViewGroup viewGroup) { + private static ViewGroup findRootViewTag(ViewGroup viewGroup) { UiThreadUtil.assertOnUiThread(); ViewParent parent = viewGroup; - while (parent != null && !(parent instanceof ReactRootView)) { + while (parent != null && !(parent instanceof ReactRootView || RNGHModalUtils.isDialogRootViewGroup(parent))) { parent = parent.getParent(); } if (parent == null) { throw new IllegalStateException("View " + viewGroup + " has not been mounted under" + " ReactRootView"); } - return (ReactRootView) parent; + return (ViewGroup) parent; } public RNGestureHandlerRootHelper(ReactContext context, ViewGroup wrappedView) { @@ -76,7 +77,7 @@ public void tearDown() { module.unregisterRootHelper(this); } - public ReactRootView getRootView() { + public ViewGroup getRootView() { return mReactRootView; } @@ -99,7 +100,11 @@ protected void onCancel() { long time = SystemClock.uptimeMillis(); MotionEvent event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0, 0, 0); event.setAction(MotionEvent.ACTION_CANCEL); - mReactRootView.onChildStartedNativeGesture(event); + if (mReactRootView instanceof ReactRootView) { + ((ReactRootView) mReactRootView).onChildStartedNativeGesture(event); + } else { + RNGHModalUtils.dialogRootViewGroupOnChildStartedNativeGesture(mReactRootView, event); + } } } From 289694703408fa4688dc88548391b11b609ea481 Mon Sep 17 00:00:00 2001 From: osdnk Date: Thu, 30 Jan 2020 01:21:59 +0100 Subject: [PATCH 2/8] lint --- .../facebook/react/views/modal/RNGHModalUtils.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java index 29e5fea99b..dfd28938d7 100644 --- a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java +++ b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java @@ -6,12 +6,11 @@ import android.view.ViewParent; public class RNGHModalUtils { - static public void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { - ((ReactModalHostView.DialogRootViewGroup) modal).onChildStartedNativeGesture(androidEvent); - } - - static public boolean isDialogRootViewGroup(ViewParent modal) { - return modal instanceof ReactModalHostView.DialogRootViewGroup; - } + static public void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { + ((ReactModalHostView.DialogRootViewGroup) modal).onChildStartedNativeGesture(androidEvent); + } + static public boolean isDialogRootViewGroup(ViewParent modal) { + return modal instanceof ReactModalHostView.DialogRootViewGroup; + } } From 04aa0774f2f3280962c0d4c60a0dc1861fb2553d Mon Sep 17 00:00:00 2001 From: osdnk Date: Thu, 30 Jan 2020 15:06:56 +0100 Subject: [PATCH 3/8] Change links to software-mansion --- docs/getting-started.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 3d76582c0d..457b4ec415 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -157,11 +157,36 @@ You can check out [this example project](https://github.com/henrikra/nativeNavig Remember that you need to wrap each screen that you use in your app with `gestureHandlerRootHOC` as with native navigation libraries each screen maps to a separate root view. It will not be enough to wrap the main screen only. +### Usage with modals on Android +On Android RNGH does not work by default because modals are not located under React Native Root view in native hierarchy. +In order to make it workable, components need to be wrapped with `gestureHandlerRootHOC` (it's no-op on iOS and web). + +E.g. +```js +const ExampleWithHoc = gestureHandlerRootHOC( + function GestureExample() { + return ( + + + + ); + } +); + +export default function Example() { + return ( + + + + ); +} +``` + ### For library authors If you're using gesture handler in your component library, you may want to wrap your library's code in the `GestureHandlerRootView` component. This will avoid extra configuration in `MainActivity.java` for the user. -```js +```jsx import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default MyComponent() { From fb326a7fd1a1e80bd054fc9320c3dae9d96ec2dd Mon Sep 17 00:00:00 2001 From: osdnk Date: Thu, 30 Jan 2020 15:07:40 +0100 Subject: [PATCH 4/8] Revert unrel --- Example/draggable/index.js | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Example/draggable/index.js b/Example/draggable/index.js index 89bf100d2d..32b3b6f2c7 100644 --- a/Example/draggable/index.js +++ b/Example/draggable/index.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Animated, Modal, StyleSheet, View } from 'react-native'; +import { Animated, StyleSheet, View } from 'react-native'; import { PanGestureHandler, @@ -9,7 +9,6 @@ import { import { USE_NATIVE_DRIVER } from '../config'; import { LoremIpsum } from '../common'; -import gestureHandlerRootHOC from '../../gestureHandlerRootHOC'; export class DraggableBox extends Component { constructor(props) { @@ -62,26 +61,14 @@ export class DraggableBox extends Component { } } -const ExampleWithHoc = gestureHandlerRootHOC( - class Example extends Component { - render() { - return ( - - - - - - ); - } - } -); - -export default class WrappedExample extends React.Component { +export default class Example extends Component { render() { return ( - - - + + + + + ); } } From 6920636cd3dd1286fef5bb032a56b901af2238fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Thu, 30 Jan 2020 15:08:17 +0100 Subject: [PATCH 5/8] Update getting-started.md --- docs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 457b4ec415..b92af0503c 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -186,7 +186,7 @@ export default function Example() { If you're using gesture handler in your component library, you may want to wrap your library's code in the `GestureHandlerRootView` component. This will avoid extra configuration in `MainActivity.java` for the user. -```jsx +```js import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default MyComponent() { From bff7a3585ce26a554b4560cd008f7d0fd2e54b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Thu, 30 Jan 2020 15:08:30 +0100 Subject: [PATCH 6/8] Update RNGHModalUtils.java --- .../main/java/com/facebook/react/views/modal/RNGHModalUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java index dfd28938d7..884964c6c7 100644 --- a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java +++ b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java @@ -1,6 +1,5 @@ package com.facebook.react.views.modal; - import android.view.MotionEvent; import android.view.ViewGroup; import android.view.ViewParent; From 14d32831f3727499b8b9b8301c84728def6bba73 Mon Sep 17 00:00:00 2001 From: osdnk Date: Thu, 30 Jan 2020 15:15:26 +0100 Subject: [PATCH 7/8] Add comment --- .../java/com/facebook/react/views/modal/RNGHModalUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java index 884964c6c7..792ae04ad8 100644 --- a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java +++ b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java @@ -4,6 +4,12 @@ import android.view.ViewGroup; import android.view.ViewParent; +/** + * For handling gestures inside RNGH we need to have access to some methods of + * `ReactModalHostView.DialogRootViewGroup`. This class is not available outside + * package so this file exports important features. + */ + public class RNGHModalUtils { static public void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { ((ReactModalHostView.DialogRootViewGroup) modal).onChildStartedNativeGesture(androidEvent); From b816cab12323d8dc0fa319c06b88653f923a7bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Mon, 3 Feb 2020 12:37:13 +0100 Subject: [PATCH 8/8] reorder static public --- .../java/com/facebook/react/views/modal/RNGHModalUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java index 792ae04ad8..b7e9858163 100644 --- a/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java +++ b/android/src/main/java/com/facebook/react/views/modal/RNGHModalUtils.java @@ -11,11 +11,11 @@ */ public class RNGHModalUtils { - static public void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { + public static void dialogRootViewGroupOnChildStartedNativeGesture(ViewGroup modal, MotionEvent androidEvent) { ((ReactModalHostView.DialogRootViewGroup) modal).onChildStartedNativeGesture(androidEvent); } - static public boolean isDialogRootViewGroup(ViewParent modal) { + public static boolean isDialogRootViewGroup(ViewParent modal) { return modal instanceof ReactModalHostView.DialogRootViewGroup; } }