mirror of
https://github.com/status-im/react-native.git
synced 2025-01-14 11:34:23 +00:00
[ReactNative] Delay sending touches to JS until dependent (native) gesture recognizers fail
Summary: Previously, JS touches were being interpreted simultaneously with native gesture recognizers.
This commit is contained in:
parent
205a2c0bfc
commit
2d66e10ec4
@ -23,6 +23,7 @@
|
|||||||
@implementation RCTTouchHandler
|
@implementation RCTTouchHandler
|
||||||
{
|
{
|
||||||
__weak RCTBridge *_bridge;
|
__weak RCTBridge *_bridge;
|
||||||
|
BOOL _dispatchedInitialTouches;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arrays managed in parallel tracking native touch object along with the
|
* Arrays managed in parallel tracking native touch object along with the
|
||||||
@ -42,9 +43,10 @@
|
|||||||
{
|
{
|
||||||
RCTAssertParam(bridge);
|
RCTAssertParam(bridge);
|
||||||
|
|
||||||
if ((self = [super initWithTarget:nil action:NULL])) {
|
if ((self = [super initWithTarget:self action:@selector(handleGestureUpdate:)])) {
|
||||||
|
|
||||||
_bridge = bridge;
|
_bridge = bridge;
|
||||||
|
_dispatchedInitialTouches = NO;
|
||||||
_nativeTouches = [[NSMutableOrderedSet alloc] init];
|
_nativeTouches = [[NSMutableOrderedSet alloc] init];
|
||||||
_reactTouches = [[NSMutableArray alloc] init];
|
_reactTouches = [[NSMutableArray alloc] init];
|
||||||
_touchViews = [[NSMutableArray alloc] init];
|
_touchViews = [[NSMutableArray alloc] init];
|
||||||
@ -216,6 +218,17 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)handleGestureUpdate:(UIGestureRecognizer *)gesture {
|
||||||
|
// If the gesture just recognized, send all the touches over to JS as if they just began
|
||||||
|
if (self.state == UIGestureRecognizerStateBegan) {
|
||||||
|
[self _updateAndDispatchTouches:[_nativeTouches set] eventName:@"topTouchStart" originatingTime:0];
|
||||||
|
|
||||||
|
// We store this flag separately from `state` because after a gesture is recognized, its `state` changes immediately but its action (that is, this method) isn't fired until dependent gesture recognizers have failed. We only want to send move/end/cancel touch updates if we've sent the touchStart events.
|
||||||
|
_dispatchedInitialTouches = YES;
|
||||||
|
}
|
||||||
|
// For the other states, we could dispatch the updates here but since we specifically send info about which touches changed, it's simpler to dispatch the updates from the raw touch methods below.
|
||||||
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
[super touchesBegan:touches withEvent:event];
|
[super touchesBegan:touches withEvent:event];
|
||||||
@ -223,21 +236,20 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
|
|||||||
// "start" has to record new touches before extracting the event.
|
// "start" has to record new touches before extracting the event.
|
||||||
// "end"/"cancel" needs to remove the touch *after* extracting the event.
|
// "end"/"cancel" needs to remove the touch *after* extracting the event.
|
||||||
[self _recordNewTouches:touches];
|
[self _recordNewTouches:touches];
|
||||||
[self _updateAndDispatchTouches:touches eventName:@"topTouchStart" originatingTime:event.timestamp];
|
if (_dispatchedInitialTouches) {
|
||||||
|
[self _updateAndDispatchTouches:touches eventName:@"topTouchStart" originatingTime:event.timestamp];
|
||||||
self.state = UIGestureRecognizerStateBegan;
|
self.state = UIGestureRecognizerStateChanged;
|
||||||
|
} else {
|
||||||
|
self.state = UIGestureRecognizerStateBegan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
[super touchesMoved:touches withEvent:event];
|
[super touchesMoved:touches withEvent:event];
|
||||||
if (self.state == UIGestureRecognizerStateFailed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self _updateAndDispatchTouches:touches eventName:@"topTouchMove" originatingTime:event.timestamp];
|
if (_dispatchedInitialTouches) {
|
||||||
|
[self _updateAndDispatchTouches:touches eventName:@"topTouchMove" originatingTime:event.timestamp];
|
||||||
if (self.state == UIGestureRecognizerStateBegan) {
|
|
||||||
self.state = UIGestureRecognizerStateChanged;
|
self.state = UIGestureRecognizerStateChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,27 +257,33 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
|
|||||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
[super touchesEnded:touches withEvent:event];
|
[super touchesEnded:touches withEvent:event];
|
||||||
[self _updateAndDispatchTouches:touches eventName:@"topTouchEnd" originatingTime:event.timestamp];
|
|
||||||
[self _recordRemovedTouches:touches];
|
|
||||||
|
|
||||||
if (RCTAllTouchesAreCancelledOrEnded(event.allTouches)) {
|
if (_dispatchedInitialTouches) {
|
||||||
self.state = UIGestureRecognizerStateEnded;
|
[self _updateAndDispatchTouches:touches eventName:@"topTouchEnd" originatingTime:event.timestamp];
|
||||||
} else if (RCTAnyTouchesChanged(event.allTouches)) {
|
|
||||||
self.state = UIGestureRecognizerStateChanged;
|
if (RCTAllTouchesAreCancelledOrEnded(event.allTouches)) {
|
||||||
|
self.state = UIGestureRecognizerStateEnded;
|
||||||
|
} else if (RCTAnyTouchesChanged(event.allTouches)) {
|
||||||
|
self.state = UIGestureRecognizerStateChanged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
[self _recordRemovedTouches:touches];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
[super touchesCancelled:touches withEvent:event];
|
[super touchesCancelled:touches withEvent:event];
|
||||||
[self _updateAndDispatchTouches:touches eventName:@"topTouchCancel" originatingTime:event.timestamp];
|
|
||||||
[self _recordRemovedTouches:touches];
|
|
||||||
|
|
||||||
if (RCTAllTouchesAreCancelledOrEnded(event.allTouches)) {
|
if (_dispatchedInitialTouches) {
|
||||||
self.state = UIGestureRecognizerStateCancelled;
|
[self _updateAndDispatchTouches:touches eventName:@"topTouchCancel" originatingTime:event.timestamp];
|
||||||
} else if (RCTAnyTouchesChanged(event.allTouches)) {
|
|
||||||
self.state = UIGestureRecognizerStateChanged;
|
if (RCTAllTouchesAreCancelledOrEnded(event.allTouches)) {
|
||||||
|
self.state = UIGestureRecognizerStateCancelled;
|
||||||
|
} else if (RCTAnyTouchesChanged(event.allTouches)) {
|
||||||
|
self.state = UIGestureRecognizerStateChanged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
[self _recordRemovedTouches:touches];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGestureRecognizer
|
- (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGestureRecognizer
|
||||||
@ -278,4 +296,8 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)reset {
|
||||||
|
_dispatchedInitialTouches = NO;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user