[ReactNative] Block native from becoming js responder

This commit is contained in:
Andrei Coman 2015-06-19 15:58:12 -07:00
parent 93e98da908
commit 5c1ac2a753
4 changed files with 20 additions and 7 deletions

View File

@ -15,10 +15,11 @@ var RCTUIManager = require('NativeModules').UIManager;
var ReactNativeTagHandles = require('ReactNativeTagHandles');
var ReactNativeGlobalResponderHandler = {
onChange: function(from: string, to: string) {
onChange: function(from: string, to: string, blockNativeResponder: boolean) {
if (to !== null) {
RCTUIManager.setJSResponder(
ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(to)
ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(to),
blockNativeResponder
);
} else {
RCTUIManager.clearJSResponder();

View File

@ -73,6 +73,11 @@ var currentCentroidY = TouchHistoryMath.currentCentroidY;
* // Another component has become the responder, so this gesture
* // should be cancelled
* },
* onShouldBlockNativeResponder: (evt, gestureState) => {
* // Returns whether this component should block native components from becoming the JS
* // responder. Returns true by default. Is currently only supported on android.
* return true;
* },
* });
* },
*
@ -241,6 +246,7 @@ var PanResponder = {
* - `onPanResponderMove: (e, gestureState) => {...}`
* - `onPanResponderTerminate: (e, gestureState) => {...}`
* - `onPanResponderTerminationRequest: (e, gestureState) => {...}`
* - 'onShouldBlockNativeResponder: (e, gestureState) => {...}'
*
* In general, for events that have capture equivalents, we update the
* gestureState once in the capture phase and can use it in the bubble phase
@ -298,6 +304,9 @@ var PanResponder = {
gestureState.dx = 0;
gestureState.dy = 0;
config.onPanResponderGrant && config.onPanResponderGrant(e, gestureState);
// TODO: t7467124 investigate if this can be removed
return config.onShouldBlockNativeResponder === undefined ? true :
config.onShouldBlockNativeResponder();
},
onResponderReject: function(e) {

View File

@ -55,13 +55,14 @@ var trackedTouchCount = 0;
*/
var previousActiveTouches = 0;
var changeResponder = function(nextResponderID) {
var changeResponder = function(nextResponderID, blockNativeResponder) {
var oldResponderID = responderID;
responderID = nextResponderID;
if (ResponderEventPlugin.GlobalResponderHandler !== null) {
ResponderEventPlugin.GlobalResponderHandler.onChange(
oldResponderID,
nextResponderID
nextResponderID,
blockNativeResponder
);
}
};
@ -379,6 +380,7 @@ function setResponderAndExtractTransfer(
grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(grantEvent);
var blockNativeResponder = executeDirectDispatch(grantEvent) === true;
if (responderID) {
var terminationRequestEvent = ResponderSyntheticEvent.getPooled(
@ -404,7 +406,7 @@ function setResponderAndExtractTransfer(
terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(terminateEvent);
extracted = accumulate(extracted, [grantEvent, terminateEvent]);
changeResponder(wantsResponderID);
changeResponder(wantsResponderID, blockNativeResponder);
} else {
var rejectEvent = ResponderSyntheticEvent.getPooled(
eventTypes.responderReject,
@ -417,7 +419,7 @@ function setResponderAndExtractTransfer(
}
} else {
extracted = accumulate(extracted, grantEvent);
changeResponder(wantsResponderID);
changeResponder(wantsResponderID, blockNativeResponder);
}
return extracted;
}

View File

@ -1215,7 +1215,8 @@ RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag
* JS sets what *it* considers to be the responder. Later, scroll views can use
* this in order to determine if scrolling is appropriate.
*/
RCT_EXPORT_METHOD(setJSResponder:(NSNumber *)reactTag)
RCT_EXPORT_METHOD(setJSResponder:(NSNumber *)reactTag
blockNativeResponder:(BOOL)blockNativeResponder)
{
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
_jsResponder = viewRegistry[reactTag];