Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual Activation Gestures eats first touch input after foregrounding on iOS. #3205

Open
tpcstld opened this issue Nov 9, 2024 · 3 comments
Labels
Can repro It is confirmed we can reproduce the issue Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided

Comments

@tpcstld
Copy link

tpcstld commented Nov 9, 2024

Description

Let's create a simple barebones app that uses a manually activated pan gesture handler.

import * as React from "react";
import { ScrollView, View } from "react-native";
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from "react-native-gesture-handler";

function useGesture() {
  return React.useMemo(() => {
    return (
      Gesture.Pan()
        .manualActivation(true)
    );
  }, []);
}

export default function HomeScreen() {
  const gesture = useGesture();

  return (
    <GestureHandlerRootView>
      <GestureDetector gesture={gesture}>
        <ScrollView>
          <View
            style={{ width: "100%", height: 300, backgroundColor: "red" }}
          />
          <View
            style={{ width: "100%", height: 300, backgroundColor: "blue" }}
          />
        </ScrollView>
      </GestureDetector>
    </GestureHandlerRootView>
  );
}

Steps to reproduce

  1. Install and open the app on a physical iOS phone.
  2. Put the code above into your app. It may be important that it is directly rendered, and not through react-native-screens or something.
  3. Swipe up and down to observe the overscroll effect.
  4. Background the app by swiping up on the iOS navigation pill.
  5. Foreground the app by tapping on the Home screen icon.
  6. Swipe up or down.

You will observe that the first swipe does not register. We don't see any overscroll effect on the ScrollView. A second swipe will have the proper effect and feedback.

PXL.Nov.9.2024.mp4

From some light debugging I've done I noticed that:

  1. Disabled gestures (i.e. gestures with enabled(false)) still cause this problem.
  2. manualActivation(false) gestures do not have this problem.
  3. Setting something like hitSlop({bottom: -100}) does not fix the issue either.
  4. Failing the gesture does not work either.

That's about all the debugging I've done so far, and please double check my work. :)

Snack or a link to a repository

https://github.com/tpcstld/rn-stuff/blob/scrolling-repro/app/_layout.tsx

Gesture Handler version

2.20.2

React Native version

0.74.5

Platforms

iOS

JavaScript runtime

None

Workflow

None

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Real device

Device model

iPhone 16 Pro

Acknowledgements

Yes

@github-actions github-actions bot added Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided labels Nov 9, 2024
@tpcstld
Copy link
Author

tpcstld commented Nov 12, 2024

I don't have a 100% confirmation on this, but I think this is an issue that only appears on iOS 18.1

@j-piasecki
Copy link
Member

I was also able to reproduce it on iOS 16.7.

@j-piasecki j-piasecki added the Can repro It is confirmed we can reproduce the issue label Nov 13, 2024
@christianbaroni
Copy link

I ran into this too. I'm not sure whether this is addressing the root issue — may also want guards for macOS — but here's a patch that resolves it:

diff --git a/node_modules/react-native-gesture-handler/apple/RNGestureHandler.mm b/node_modules/react-native-gesture-handler/apple/RNGestureHandler.mm
index 43d11b4..276024c 100644
--- a/node_modules/react-native-gesture-handler/apple/RNGestureHandler.mm
+++ b/node_modules/react-native-gesture-handler/apple/RNGestureHandler.mm
@@ -390,12 +390,28 @@ - (void)setManualActivation:(BOOL)manualActivation
     if (_recognizer.view != nil) {
       [_recognizer.view addGestureRecognizer:_manualActivationRecognizer];
     }
+
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(handleAppWillResignActive:)
+                                                 name:UIApplicationWillResignActiveNotification
+                                               object:nil];
   } else if (_manualActivationRecognizer != nil) {
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIApplicationWillResignActiveNotification
+                                                  object:nil];
     [_manualActivationRecognizer.view removeGestureRecognizer:_manualActivationRecognizer];
     _manualActivationRecognizer = nil;
   }
 }
 
+- (void)handleAppWillResignActive:(NSNotification *)notification
+{
+  if (_manualActivationRecognizer != nil && _manualActivationRecognizer.enabled) {
+    _manualActivationRecognizer.enabled = NO;
+    _manualActivationRecognizer.enabled = YES;
+  }
+}
+
 - (void)bindManualActivationToView:(RNGHUIView *)view
 {
   if (_manualActivationRecognizer != nil) {

Was seeing the issue with this gesture:

Gesture.Simultaneous(Gesture.Pan().manualActivation(true), Gesture.Native())

https://github.com/rainbow-me/rainbow/blob/%40christian/browser-upgrades/src/components/DappBrowser/hooks/useBrowserScrollView.ts#L108-L319

Which is used here with an Animated.ScrollView:
https://github.com/rainbow-me/rainbow/blob/%40christian/browser-upgrades/src/components/DappBrowser/DappBrowser.tsx#L126-L146

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Can repro It is confirmed we can reproduce the issue Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided
Projects
None yet
Development

No branches or pull requests

3 participants