You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For example, if you have a component at the edge like a slider, it's touches are canceled if you start sliding from the left edge. That might be alright if the screen has gesture enabled, but I don't think it's correct to do that when gestureEnabled: false for a screen (totally possible I am missing a case).
I haven't worked with Objective C before but I think the issue is because of this.
if (!topScreen.gestureEnabled || _controller.viewControllers.count < 2) {
returnNO;
}
#if TARGET_OS_TV
returnYES;
#else
if ([gestureRecognizer isKindOfClass:[RNSGestureRecognizer class]]) {
// if we do not set any explicit `semanticContentAttribute`, it is `UISemanticContentAttributeUnspecified` instead
Specifically, the part where touchHandler is cancelled and reset without checking if gesture's enabled for a screen.
I fixed it by applying this patch locally that tests if topScreen.gestureEnabled is truthy before cancelling/resetting touch handlers :
@@
diff --git a/node_modules/react-native-screens/ios/RNSScreenStack.m b/node_modules/react-native-screens/ios/RNSScreenStack.m
index 7b76e12..f44f11a 100644
--- a/node_modules/react-native-screens/ios/RNSScreenStack.m
+++ b/node_modules/react-native-screens/ios/RNSScreenStack.m
@@ -509,20 +509,22 @@
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
- // cancel touches in parent, this is needed to cancel RN touch events. For example when Touchable
- // item is close to an edge and we start pulling from edge we want the Touchable to be cancelled.
- // Without the below code the Touchable will remain active (highlighted) for the duration of back
- // gesture and onPress may fire when we release the finger.
- UIView *parent = _controller.view;
- while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)]) parent = parent.superview;
- if (parent != nil) {
- RCTTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
- [touchHandler cancel];
- [touchHandler reset];
- }
-
RNSScreenView *topScreen = (RNSScreenView *)_controller.viewControllers.lastObject.view;
+ if(topScreen.gestureEnabled) {
+ // cancel touches in parent, this is needed to cancel RN touch events. For example when Touchable
+ // item is close to an edge and we start pulling from edge we want the Touchable to be cancelled.
+ // Without the below code the Touchable will remain active (highlighted) for the duration of back
+ // gesture and onPress may fire when we release the finger.
+ UIView *parent = _controller.view;
+ while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)]) parent = parent.superview;
+ if (parent != nil) {
+ RCTTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
+ [touchHandler cancel];
+ [touchHandler reset];
+ }
+ }
+
if (!topScreen.gestureEnabled || _controller.viewControllers.count < 2) {
return NO;
}
Steps To Reproduce
Use native stack with gestureEnabled: false on iOS
Use a slider. For ex this, just import and use <Slider maximumValue={100} />
Start sliding from the left edge, you'll see that the slider is interrupted
Expected behavior
Touch handler shouldn't be interrupted when gestureEnabled:false
Actual behavior
Touch handler is interrupted
Snack or minimal code example
Package versions
React Native: 0.63.4
React Native Screens: 3.4.0
The text was updated successfully, but these errors were encountered:
owaiswiz
changed the title
RN Touch events are canceled even when {gestureEnabled: false} on false when using native stack navigation
RN Touch events are canceled even when {gestureEnabled: false} on iOS when using native stack navigation
Jul 21, 2021
If you are in the first screen in stack and the gesture is enabled on it, it will still cancel the touches even though there will be no option to go back. I think the cancelling code should only be triggered when the method is going to return YES. Maybe it would be best to refactor the code to have a single point of return with YES value, and trigger the canceling code before it. Could you submit such a PR?
Description
For example, if you have a component at the edge like a slider, it's touches are canceled if you start sliding from the left edge. That might be alright if the screen has gesture enabled, but I don't think it's correct to do that when gestureEnabled: false for a screen (totally possible I am missing a case).
I haven't worked with Objective C before but I think the issue is because of this.
react-native-screens/ios/RNSScreenStack.m
Lines 530 to 553 in c3998ad
Specifically, the part where touchHandler is cancelled and reset without checking if gesture's enabled for a screen.
I fixed it by applying this patch locally that tests if topScreen.gestureEnabled is truthy before cancelling/resetting touch handlers :
Steps To Reproduce
<Slider maximumValue={100} />
Expected behavior
Touch handler shouldn't be interrupted when gestureEnabled:false
Actual behavior
Touch handler is interrupted
Snack or minimal code example
Package versions
The text was updated successfully, but these errors were encountered: