Skip to content

Commit 181a6f6

Browse files
authored
[iOS] Prevent duplicated events in Native gesture handling (#4125)
## Description I've noticed that when `Native` gesture is not attached to `UIControl` it sends different events (e.g. events containing `x` and `y` positions). I've changed that to mimic behavior from #4102 ## Test plan <details> <summary>Tested on the following example</summary> ```tsx import { ScrollView, StyleSheet, View } from 'react-native'; import { GestureDetector, GestureHandlerRootView, ScrollView as RNGHScrollView, Touchable, useNativeGesture, } from 'react-native-gesture-handler'; export default function App() { const g = useNativeGesture({ onBegin: () => { console.log(Date.now(), 'gesture begin'); }, onActivate: () => { console.log(Date.now(), 'gesture activate'); }, onUpdate: (e) => { console.log(Date.now(), 'gesture update', e); }, onDeactivate: () => { console.log(Date.now(), 'gesture deactivate'); }, onFinalize: () => { console.log(Date.now(), 'gesture finalize'); }, shouldCancelWhenOutside: false, }); return ( <GestureHandlerRootView style={styles.container}> <Touchable cancelOnLeave={false} style={{ width: 150, height: 45, backgroundColor: 'crimson', borderRadius: 8, }} /> <GestureDetector gesture={g}> <ScrollView style={[styles.scrollView, { backgroundColor: 'green' }]}> {BOXES.map((color, i) => ( <View key={i} style={[styles.box, { backgroundColor: color }]} /> ))} </ScrollView> </GestureDetector> <RNGHScrollView onBegin={() => { console.log(Date.now(), 'gesture begin'); }} onActivate={() => { console.log(Date.now(), 'gesture activate'); }} onUpdate={() => { console.log(Date.now(), 'gesture update'); }} onDeactivate={() => { console.log(Date.now(), 'gesture deactivate'); }} onFinalize={() => { console.log(Date.now(), 'gesture finalize'); }} style={[styles.scrollView, { backgroundColor: 'blue' }]}> {BOXES.map((color, i) => ( <View key={i} style={[styles.box, { backgroundColor: color }]} /> ))} </RNGHScrollView> </GestureHandlerRootView> ); } const BOXES = [ '#ff6b6b', '#ffd93d', '#6bcb77', '#4d96ff', '#c77dff', '#ff9f43', '#ee5a24', '#0652dd', '#1289a7', '#d980fa', ]; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, scrollView: { width: 200, maxHeight: 250, marginVertical: 8, }, box: { width: '100%', height: 60, marginBottom: 4, }, }); ``` </details>
1 parent 5a847d1 commit 181a6f6

3 files changed

Lines changed: 28 additions & 6 deletions

File tree

packages/react-native-gesture-handler/apple/Handlers/RNNativeViewHandler.mm

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,22 @@ - (void)unbindFromView
192192
[super unbindFromView];
193193
}
194194

195+
- (BOOL)shouldSuppressActiveEvent:(RNGestureHandlerEventExtraData *)extraData
196+
{
197+
if (_lastActiveExtraData != nil && [_lastActiveExtraData.data isEqualToDictionary:extraData.data]) {
198+
return YES;
199+
}
200+
201+
_lastActiveExtraData = extraData;
202+
return NO;
203+
}
204+
195205
- (void)sendActiveStateEventIfChangedForView:(UIView *)sender extraData:(RNGestureHandlerEventExtraData *)extraData
196206
{
197-
if ([_lastActiveExtraData.data isEqualToDictionary:extraData.data]) {
207+
if ([self shouldSuppressActiveEvent:extraData]) {
198208
return;
199209
}
200210

201-
_lastActiveExtraData = extraData;
202211
[self sendEventsInState:RNGestureHandlerStateActive forViewWithTag:sender.reactTag withExtraData:extraData];
203212
}
204213

@@ -245,7 +254,6 @@ - (void)handleTouchDown:(UIView *)sender forEvent:(UIEvent *)event
245254
withNumberOfTouches:event.allTouches.count
246255
withPointerType:_pointerType]];
247256

248-
_lastActiveExtraData = nil;
249257
[self sendActiveStateEventIfChangedForView:sender
250258
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
251259
withNumberOfTouches:event.allTouches.count
@@ -330,7 +338,13 @@ - (BOOL)wantsToAttachDirectlyToView
330338
return YES;
331339
}
332340

333-
#else
341+
- (void)reset
342+
{
343+
[super reset];
344+
_lastActiveExtraData = nil;
345+
}
346+
347+
#endif
334348

335349
- (RNGestureHandlerEventExtraData *)eventExtraData:(RNDummyGestureRecognizer *)recognizer
336350
{
@@ -339,6 +353,4 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(RNDummyGestureRecognizer *)r
339353
withPointerType:RNGestureHandlerMouse];
340354
}
341355

342-
#endif
343-
344356
@end

packages/react-native-gesture-handler/apple/RNGestureHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
- (void)setConfig:(nullable NSDictionary *)config NS_REQUIRES_SUPER;
9797
- (void)updateConfig:(nullable NSDictionary *)config NS_REQUIRES_SUPER;
9898
- (void)updateRelations:(nonnull NSDictionary *)relations;
99+
- (BOOL)shouldSuppressActiveEvent:(nonnull RNGestureHandlerEventExtraData *)extraData;
99100
- (void)handleGesture:(nonnull id)recognizer;
100101
- (void)handleGesture:(nonnull id)recognizer fromReset:(BOOL)fromReset;
101102
- (void)handleGesture:(nonnull id)recognizer

packages/react-native-gesture-handler/apple/RNGestureHandler.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ - (RNGHUIView *)chooseViewForInteraction:(UIGestureRecognizer *)recognizer
307307
return [self isViewParagraphComponent:recognizer.view] ? recognizer.view.subviews[0] : recognizer.view;
308308
}
309309

310+
- (BOOL)shouldSuppressActiveEvent:(RNGestureHandlerEventExtraData *)extraData
311+
{
312+
return NO;
313+
}
314+
310315
- (void)handleGesture:(UIGestureRecognizer *)recognizer
311316
{
312317
[self handleGesture:recognizer fromReset:NO];
@@ -368,6 +373,10 @@ - (void)handleGesture:(UIGestureRecognizer *)recognizer
368373

369374
RNGestureHandlerEventExtraData *eventData = [self eventExtraData:recognizer];
370375

376+
if (state == RNGestureHandlerStateActive && [self shouldSuppressActiveEvent:eventData]) {
377+
return;
378+
}
379+
371380
NSNumber *tag = [self chooseViewForInteraction:recognizer].reactTag;
372381

373382
if (tag == nil && _actionType == RNGestureHandlerActionTypeNativeDetector) {

0 commit comments

Comments
 (0)