Summary:
This PR fixes https://github.com/facebook/react-native/issues/19637.

Summary of the issue: on Android, transformed touchables have press issues because the touchable's measurements are incorrect in the release phase. `UIManager.measure()` returns an incorrect size and position as explained [here](https://github.com/facebook/react-native/issues/19637#issuecomment-396065914)

This is easily seen with the inspector :

**Screenshot of a { scale: 2 } transform**
The real view (scaled) is in pink, the incorrect touchable area is in blue.
<img src="https://user-images.githubusercontent.com/110431/41190133-8d07ad02-6bd9-11e8-873d-93776a007309.png" width="200"/>

**Screenshot of a { rotateZ: "-45deg" } transform**
The real view (rotated) is in pink, the incorrect touchable area is in blue.
<img src="https://user-images.githubusercontent.com/110431/41190136-a1a079a6-6bd9-11e8-906d-729015bcab6b.png" width="200"/>

## Changelog

[Android] [Fixed] - Fix UIManager.measure()
Pull Request resolved: https://github.com/facebook/react-native/pull/25836

Test Plan:
Android now produces the same results as iOS as seen on these screenshots

| Android without fix | Android with fix | iOS |
| --- | --- | --- |
| ![Screenshot_1564133103](https://user-images.githubusercontent.com/110431/61941632-28729b00-af98-11e9-9706-b13968b79df5.png) | ![Screenshot_1564130198](https://user-images.githubusercontent.com/110431/61941631-28729b00-af98-11e9-9ff3-5f2748077dbe.png) | ![Simulator Screen Shot - iPhone X - 2019-07-26 at 11 19 34](https://user-images.githubusercontent.com/110431/61941633-28729b00-af98-11e9-8dc4-22b61178242e.png) |

Reviewed By: cpojer

Differential Revision: D16598914

Pulled By: makovkastar

fbshipit-source-id: d56b008b717ea17731fb09001cbd395aa1b044fe
This commit is contained in:
Florian Cargoët 2019-08-05 04:36:07 -07:00 коммит произвёл Facebook Github Bot
Родитель 2956eb266f
Коммит 28d50189f3
1 изменённых файлов: 40 добавлений и 6 удалений

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

@ -7,6 +7,8 @@
package com.facebook.react.uimanager;
import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@ -74,6 +76,7 @@ public class NativeViewHierarchyManager {
private final LayoutAnimationController mLayoutAnimator = new LayoutAnimationController();
private final SparseArray<SparseIntArray> mTagsToPendingIndicesToDelete = new SparseArray<>();
private final int[] mDroppedViewArray = new int[100];
private final RectF mBoundingBox = new RectF();
private boolean mLayoutAnimationEnabled;
private PopupMenu mPopupMenu;
@ -649,16 +652,47 @@ public class NativeViewHierarchyManager {
if (rootView == null) {
throw new NoSuchNativeViewException("Native view " + tag + " is no longer on screen");
}
rootView.getLocationInWindow(outputBuffer);
computeBoundingBox(rootView, outputBuffer);
int rootX = outputBuffer[0];
int rootY = outputBuffer[1];
computeBoundingBox(v, outputBuffer);
outputBuffer[0] -= rootX;
outputBuffer[1] -= rootY;
}
v.getLocationInWindow(outputBuffer);
private void computeBoundingBox(View view, int[] outputBuffer) {
mBoundingBox.set(0, 0, view.getWidth(), view.getHeight());
mapRectFromViewToWindowCoords(view, mBoundingBox);
outputBuffer[0] = outputBuffer[0] - rootX;
outputBuffer[1] = outputBuffer[1] - rootY;
outputBuffer[2] = v.getWidth();
outputBuffer[3] = v.getHeight();
outputBuffer[0] = Math.round(mBoundingBox.left);
outputBuffer[1] = Math.round(mBoundingBox.top);
outputBuffer[2] = Math.round(mBoundingBox.right - mBoundingBox.left);
outputBuffer[3] = Math.round(mBoundingBox.bottom - mBoundingBox.top);
}
private void mapRectFromViewToWindowCoords(View view, RectF rect) {
Matrix matrix = view.getMatrix();
if (!matrix.isIdentity()) {
matrix.mapRect(rect);
}
rect.offset(view.getLeft(), view.getTop());
ViewParent parent = view.getParent();
while (parent instanceof View) {
View parentView = (View) parent;
rect.offset(-parentView.getScrollX(), -parentView.getScrollY());
matrix = parentView.getMatrix();
if (!matrix.isIdentity()) {
matrix.mapRect(rect);
}
rect.offset(parentView.getLeft(), parentView.getTop());
parent = parentView.getParent();
}
}
/**