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

Fix scroll view handler state change events #2985

Merged
merged 9 commits into from
Aug 5, 2024
Merged
25 changes: 24 additions & 1 deletion apple/Handlers/RNNativeViewHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,27 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler

- (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
{
[self setStateIfScrollView:UIGestureRecognizerStatePossible];
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
[_gestureHandler setCurrentPointerType:event];
[_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
{
[self setStateIfScrollView:UIGestureRecognizerStateChanged];
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
[_gestureHandler.pointerTracker touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
{
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
self.state = UIGestureRecognizerStateFailed;
[self reset];

// For now, we are handling only the scroll view case.
// If more views need special treatment, then we can switch to a delegate pattern
if (![self isScrollView]) {
[self reset];
}
}

- (void)touchesCancelled:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
Expand All @@ -69,6 +76,22 @@ - (void)reset
[_gestureHandler reset];
}

- (void)setStateIfScrollView:(UIGestureRecognizerState)state
{
if ([self isScrollView]) {
self.state = state;
}
}

- (BOOL)isScrollView
{
#ifdef RCT_NEW_ARCH_ENABLED
return [self.view isKindOfClass:[RCTScrollViewComponentView class]];
#else
return [self.view isKindOfClass:[RCTScrollView class]];
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
#endif
}

@end

#pragma mark RNNativeViewGestureHandler
Expand Down
44 changes: 43 additions & 1 deletion apple/RNGestureHandler.m → apple/RNGestureHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@

#if !TARGET_OS_OSX
#import <UIKit/UIGestureRecognizerSubclass.h>
#import <UIKit/UIPanGestureRecognizer.h>
#endif

#import <React/UIView+React.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <React/RCTScrollViewComponentView.h>
#else
#import <React/RCTScrollView.h>
#endif

@interface UIGestureRecognizer (GestureHandler)
@property (nonatomic, readonly) RNGestureHandler *gestureHandler;
@end
Expand Down Expand Up @@ -205,7 +212,7 @@ - (void)setCurrentPointerTypeToMouse

- (UITouchType)getPointerType
{
return _pointerType;
return (UITouchType)_pointerType;
}

- (void)bindToView:(RNGHUIView *)view
Expand Down Expand Up @@ -474,6 +481,10 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
return YES;
}

if ([self areRecognizersCompatible:gestureRecognizer otherRecognizer:otherGestureRecognizer]) {
return YES;
}

RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
if (handler != nil) {
if ([_simultaneousHandlers count]) {
Expand All @@ -495,6 +506,37 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
return NO;
}

- (BOOL)areRecognizersCompatible:(UIGestureRecognizer *)gestureRecognizer
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
otherRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// Check if otherGestureRecognizer is instance of UIScrollViewPanGestureRecognizer (is UIPanGestureRecognizer and has
// scrollView property)
if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
[otherGestureRecognizer respondsToSelector:@selector(scrollView)] &&
[gestureRecognizer isKindOfClass:[RNDummyGestureRecognizer class]]) {
UIView *gestureRecognizerView = gestureRecognizer.view;
UIView *otherGestureRecognizerView = otherGestureRecognizer.view;

#ifdef RCT_NEW_ARCH_ENABLED
if ([gestureRecognizerView isKindOfClass:[RCTScrollViewComponentView class]]) {
UIScrollView *scrollView = ((RCTScrollViewComponentView *)gestureRecognizerView).scrollView;
if (scrollView == otherGestureRecognizerView) {
return YES;
}
}
#else
if ([gestureRecognizerView isKindOfClass:[RCTScrollView class]]) {
UIScrollView *scrollView = [gestureRecognizerView.subviews objectAtIndex:0];
if (scrollView == otherGestureRecognizerView) {
return YES;
}
}
#endif
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
}

return NO;
}

- (void)reset
{
// do not reset states while gesture is tracking pointers, as gestureRecognizerShouldBegin
Expand Down
Loading