forked from software-mansion/react-native-gesture-handler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RNGestureHandlerManager.m
159 lines (134 loc) · 5.09 KB
/
RNGestureHandlerManager.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#import "RNGestureHandlerManager.h"
#import <React/RCTLog.h>
#import <React/RCTViewManager.h>
#import <React/RCTComponent.h>
#import <React/RCTRootView.h>
#import <React/RCTTouchHandler.h>
#import "RNGestureHandlerState.h"
#import "RNGestureHandler.h"
@interface RNGestureHandlerManager () <RNGestureHandlerEventEmitter, RNRootViewGestureRecognizerDelegate>
@end
@implementation RNGestureHandlerManager
{
RNGestureHandlerRegistry *_registry;
RCTUIManager *_uiManager;
NSMutableSet<UIView*> *_rootViews;
RCTEventDispatcher *_eventDispatcher;
}
- (instancetype)initWithUIManager:(RCTUIManager *)uiManager
eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if ((self = [super init])) {
_uiManager = uiManager;
_eventDispatcher = eventDispatcher;
_registry = [RNGestureHandlerRegistry new];
_rootViews = [NSMutableSet new];
}
return self;
}
- (void)createGestureHandler:(NSNumber *)viewTag
withName:(NSString *)handlerName
tag:(NSNumber *)handlerTag
config:(NSDictionary *)config
{
static NSDictionary *map;
static dispatch_once_t mapToken;
dispatch_once(&mapToken, ^{
map = @{
@"PanGestureHandler" : [RNPanGestureHandler class],
@"TapGestureHandler" : [RNTapGestureHandler class],
@"LongPressGestureHandler": [RNLongPressGestureHandler class],
@"NativeViewGestureHandler": [RNNativeViewGestureHandler class],
@"PinchGestureHandler": [RNPinchGestureHandler class],
@"RotationGestureHandler": [RNRotationGestureHandler class],
};
});
Class nodeClass = map[handlerName];
if (!nodeClass) {
RCTLogError(@"Gesture handler type %@ is not supported", handlerName);
return;
}
RNGestureHandler *gestureHandler = [[nodeClass alloc] initWithTag:handlerTag];
[gestureHandler configure:config];
[_registry registerGestureHandler:gestureHandler forViewWithTag:viewTag];
__weak id<RNGestureHandlerEventEmitter> emitter = self;
gestureHandler.emitter = emitter;
UIView *view = [_uiManager viewForReactTag:viewTag];
[gestureHandler bindToView:view];
// register root view if not already there
[self registerRootViewIfNeeded:view];
}
- (void)updateGestureHandler:(NSNumber *)viewTag
tag:(NSNumber *)handlerTag
config:(NSDictionary *)config
{
NSArray<RNGestureHandler*> *handlers = [_registry
gestureHandlersForViewWithTag:viewTag
andTag:handlerTag];
for (RNGestureHandler *handler in handlers) {
if ([handler.tag isEqual:handlerTag]) {
[handler configure:config];
}
}
}
- (void)dropGestureHandlersForView:(NSNumber *)viewTag
{
[_registry dropGestureHandlersForViewWithTag:viewTag];
}
- (void)handleSetJSResponder:(NSNumber *)viewTag blockNativeResponder:(NSNumber *)blockNativeResponder
{
if ([blockNativeResponder boolValue]) {
for (RCTRootView *rootView in _rootViews) {
for (UIGestureRecognizer *recognizer in rootView.gestureRecognizers) {
if ([recognizer isKindOfClass:[RNRootViewGestureRecognizer class]]) {
[(RNRootViewGestureRecognizer *)recognizer blockOtherRecognizers];
}
}
}
}
}
- (void)handleClearJSResponder
{
// ignore...
}
#pragma mark Root Views Management
- (void)registerRootViewIfNeeded:(UIView*)childView
{
UIView *parent = childView;
while (parent != nil && ![parent isKindOfClass:[RCTRootView class]]) parent = parent.superview;
RCTRootView *rootView = (RCTRootView *)parent;
UIView *rootContentView = rootView.contentView;
if (rootContentView != nil && ![_rootViews containsObject:rootContentView]) {
[_rootViews addObject:rootContentView];
RNRootViewGestureRecognizer *recognizer = [RNRootViewGestureRecognizer new];
recognizer.delegate = self;
rootContentView.userInteractionEnabled = YES;
[rootContentView addGestureRecognizer:recognizer];
}
}
- (void)gestureHandlerDidActivateInRootView:(UIView*)rootView
{
// Dispatch touch cancel to JS in order to cancel all in-js recognizers
RCTTouchHandler *touchHandler;
// Find touch handlers - should be installed as the content view's recognizer
for (UIGestureRecognizer *recognizer in rootView.gestureRecognizers) {
if ([recognizer isKindOfClass:[RCTTouchHandler class]]) {
touchHandler = (RCTTouchHandler *)recognizer;
break;
}
}
// We change touch handler to disabled and back to enabled, this will trigger cancel event
// to be delivered to JS
touchHandler.enabled = NO;
touchHandler.enabled = YES;
}
#pragma mark Events
- (void)sendTouchEvent:(RNGestureHandlerEvent *)event
{
[_eventDispatcher sendEvent:event];
}
- (void)sendStateChangeEvent:(RNGestureHandlerStateChange *)event
{
[_eventDispatcher sendEvent:event];
}
@end