Ignore touch events on layout only Nodes

Summary:
Before this patch, each Node would always generate a node
region, representing the bounds of this particular Node. This set of Nodes was
used when handling touch to figure out whether we should intercept touch (i.e.
a flat Node is catching the draw), or let Android handle touch (i.e. a Node
mounted to a View will handle the touch).

This patch modifies the list of NodeRegions to exclude any Nodes that draw
nothing at all. These Nodes, having no draw output, are effectively layout
containers used to group items, so they shouldn't handle touch.

Reviewed By: sriramramani

Differential Revision: D4369484

fbshipit-source-id: 71b41611873580631f1639f368fa8d971995874f
This commit is contained in:
Ahmed El-Helw 2016-12-28 18:40:40 -08:00 committed by Facebook Github Bot
parent 2249af16b7
commit e380d6d0fd
5 changed files with 35 additions and 1 deletions

View File

@ -144,6 +144,21 @@ import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
}
}
/**
* Return whether or not this node draws anything
*
* This is used to decide whether or not to collect the NodeRegion for this node. This ensures
* that any FlatShadowNode that does not emit any DrawCommands should not bother handling touch
* (i.e. if it draws absolutely nothing, it is, for all intents and purposes, a layout only node).
*
* @return whether or not this is node draws anything
*/
boolean doesDraw() {
// if it mounts to view or draws a background, we can collect it - otherwise, no, unless a
// child suggests some alternative behavior
return mDrawView != null || mDrawBackground != null;
}
@ReactProp(name = ViewProps.BACKGROUND_COLOR)
public void setBackgroundColor(int backgroundColor) {
mDrawBackground = (backgroundColor == 0) ? null : new DrawBackgroundColor(backgroundColor);

View File

@ -81,6 +81,11 @@ import com.facebook.react.views.image.ImageResizeMode;
}
}
@Override
boolean doesDraw() {
return mDrawImage.hasImageRequest() || super.doesDraw();
}
@ReactProp(name = "shouldNotifyLoadEvents")
public void setShouldNotifyLoadEvents(boolean shouldNotifyLoadEvents) {
getMutableDrawImage().setReactTag(shouldNotifyLoadEvents ? getReactTag() : 0);

View File

@ -198,6 +198,13 @@ import com.facebook.react.uimanager.annotations.ReactProp;
performCollectAttachDetachListeners(stateBuilder);
}
@Override
boolean doesDraw() {
// assume text always draws - this is a performance optimization to avoid having to
// getText() when layout was skipped and when collectState wasn't yet called
return true;
}
@ReactProp(name = ViewProps.LINE_HEIGHT, defaultDouble = Double.NaN)
public void setLineHeight(double lineHeight) {
if (Double.isNaN(lineHeight)) {

View File

@ -85,6 +85,11 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup;
}
}
@Override
boolean doesDraw() {
return mDrawBorder != null || super.doesDraw();
}
@Override
public void setBackgroundColor(int backgroundColor) {
getMutableBorder().setBackgroundColor(backgroundColor);

View File

@ -261,7 +261,9 @@ import com.facebook.react.uimanager.events.EventDispatcher;
}
node.updateNodeRegion(left, top, right, bottom, isVirtual);
mNodeRegions.add(node.getNodeRegion());
if (node.doesDraw()) {
mNodeRegions.add(node.getNodeRegion());
}
}
/**