Fix OnLayoutEvent dispatching wrong x/y coordinates

Summary:
OnLayoutEvent was incorrectly dispatching x/y coordinates relative to native View instead of relative to parent. This was causing issues in many cases, such as when Node was mounting to a View, in which case x/y would always be 0. This diff is fixing it.

This diff also caches last OnLayoutEvent to avoid dispatching the event on every layout even when layout didn't chance.

Reviewed By: ahmedre

Differential Revision: D2955087
This commit is contained in:
Denis Koroskin 2016-02-24 17:10:33 -08:00 committed by Ahmed El-Helw
parent c36d4593fd
commit 5305f3b68e
2 changed files with 30 additions and 9 deletions

View File

@ -12,10 +12,11 @@ package com.facebook.react.flat;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.OnLayoutEvent;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
/** /**
* FlatShadowNode is a base class for all shadow node used in FlatUIImplementation. It extends * FlatShadowNode is a base class for all shadow node used in FlatUIImplementation. It extends
@ -50,6 +51,12 @@ import com.facebook.react.uimanager.ViewProps;
private int mMoveToIndexInParent; private int mMoveToIndexInParent;
private boolean mClipToBounds = false; private boolean mClipToBounds = false;
// last OnLayoutEvent info, only used when shouldNotifyOnLayout() is true.
private int mLayoutX;
private int mLayoutY;
private int mLayoutWidth;
private int mLayoutHeight;
/* package */ void handleUpdateProperties(ReactStylesDiffMap styles) { /* package */ void handleUpdateProperties(ReactStylesDiffMap styles) {
if (!mountsToView()) { if (!mountsToView()) {
// Make sure we mount this FlatShadowNode to a View if any of these properties are present. // Make sure we mount this FlatShadowNode to a View if any of these properties are present.
@ -277,6 +284,19 @@ import com.facebook.react.uimanager.ViewProps;
return mDrawView; return mDrawView;
} }
/* package */ final OnLayoutEvent obtainLayoutEvent(int x, int y, int width, int height) {
if (mLayoutX == x && mLayoutY == y && mLayoutWidth == width && mLayoutHeight == height) {
return null;
}
mLayoutX = x;
mLayoutY = y;
mLayoutWidth = width;
mLayoutHeight = height;
return OnLayoutEvent.obtain(getReactTag(), x, y, width, height);
}
/* package */ final boolean mountsToView() { /* package */ final boolean mountsToView() {
return mDrawView != null; return mDrawView != null;
} }

View File

@ -401,13 +401,14 @@ import com.facebook.react.uimanager.events.EventDispatcher;
// notify JS about layout event if requested // notify JS about layout event if requested
if (node.shouldNotifyOnLayout()) { if (node.shouldNotifyOnLayout()) {
mOnLayoutEvents.add( OnLayoutEvent layoutEvent = node.obtainLayoutEvent(
OnLayoutEvent.obtain( Math.round(node.getLayoutX()),
node.getReactTag(), Math.round(node.getLayoutY()),
(int) roundedLeft,
(int) roundedTop,
(int) (roundedRight - roundedLeft), (int) (roundedRight - roundedLeft),
(int) (roundedBottom - roundedTop))); (int) (roundedBottom - roundedTop));
if (layoutEvent != null) {
mOnLayoutEvents.add(layoutEvent);
}
} }
if (node.clipToBounds()) { if (node.clipToBounds()) {