Make FlatViewGroup implement ReactCompoundViewGroup interface

Summary: In FlatViewGroup, we flatten some react nodes into parent while mounting others into child Views. This is causing touch events being dispatched to wrong targets because child Views are \"stealing\" touch events from flattened Views. To fix the issue, implement ReactCompoundViewGroup to provide information about both virtual and non-virtual nodes.

Reviewed By: ahmedre

Differential Revision: D3018054
This commit is contained in:
Denis Koroskin 2016-03-07 20:06:32 -08:00 коммит произвёл Ahmed El-Helw
Родитель b52928c484
Коммит 89cf5c49b9
1 изменённых файлов: 28 добавлений и 3 удалений

Просмотреть файл

@ -29,7 +29,7 @@ import com.facebook.react.common.SystemClock;
import com.facebook.react.touch.OnInterceptTouchEventListener;
import com.facebook.react.touch.ReactInterceptingViewGroup;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ReactCompoundView;
import com.facebook.react.uimanager.ReactCompoundViewGroup;
import com.facebook.react.uimanager.ReactPointerEventsView;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.views.image.ImageLoadEvent;
@ -39,7 +39,7 @@ import com.facebook.react.views.image.ImageLoadEvent;
* array of DrawCommands, executing them one by one.
*/
/* package */ final class FlatViewGroup extends ViewGroup
implements ReactInterceptingViewGroup, ReactCompoundView, ReactPointerEventsView {
implements ReactInterceptingViewGroup, ReactCompoundViewGroup, ReactPointerEventsView {
/**
* Helper class that allows AttachDetachListener to invalidate the hosting View.
*/
@ -133,6 +133,16 @@ import com.facebook.react.views.image.ImageLoadEvent;
return getId();
}
@Override
public boolean interceptsTouchEvent(float touchX, float touchY) {
NodeRegion nodeRegion = anyNodeRegionWithinBounds(touchX, touchY);
if (nodeRegion != null) {
return nodeRegion.mIsVirtual;
}
return false;
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@ -257,6 +267,10 @@ import com.facebook.react.views.image.ImageLoadEvent;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (interceptsTouchEvent(ev.getX(), ev.getY())) {
return true;
}
if (mOnInterceptTouchEventListener != null &&
mOnInterceptTouchEventListener.onInterceptTouchEvent(this, ev)) {
return true;
@ -411,7 +425,7 @@ import com.facebook.react.views.image.ImageLoadEvent;
LAYOUT_REQUESTS.clear();
}
private NodeRegion virtualNodeRegionWithinBounds(float touchX, float touchY) {
private @Nullable NodeRegion virtualNodeRegionWithinBounds(float touchX, float touchY) {
for (int i = mNodeRegions.length - 1; i >= 0; --i) {
NodeRegion nodeRegion = mNodeRegions[i];
if (!nodeRegion.mIsVirtual) {
@ -426,6 +440,17 @@ import com.facebook.react.views.image.ImageLoadEvent;
return null;
}
private @Nullable NodeRegion anyNodeRegionWithinBounds(float touchX, float touchY) {
for (int i = mNodeRegions.length - 1; i >= 0; --i) {
NodeRegion nodeRegion = mNodeRegions[i];
if (nodeRegion.withinBounds(touchX, touchY)) {
return nodeRegion;
}
}
return null;
}
private View ensureViewHasNoParent(View view) {
ViewParent oldParent = view.getParent();
if (oldParent != null) {