mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-10 22:47:58 +08:00
Summary: NodeRegions are touch regions within hosting View, and while in most cases they are the same as View boundaries, there is one case where it's not true: TextNodeRegion. When mounted to a View, TextNodeRegion will have a bounds of (0,0,width,height) which is clearly different from (left,top,right,bottom). Initially I assumed they would always be the same so we could use information stored in NodeRegion (should probably be called TouchRegion) to update node's View boundaries, but it breaks RCTTextView when it mount to a View (because it would either contain incorrect bounds, or View will be laid out incorrectly). Right now touch is not working on RCTView that mounts to a View. To fix the issue, separate the 2 concepts. Reviewed By: ahmedre Differential Revision: D2816268
293 lines
8.4 KiB
Java
293 lines
8.4 KiB
Java
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
package com.facebook.react.flat;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import com.facebook.react.bridge.Callback;
|
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
import com.facebook.react.uimanager.PixelUtil;
|
|
import com.facebook.react.uimanager.UIViewOperationQueue;
|
|
|
|
/**
|
|
* FlatUIViewOperationQueue extends {@link UIViewOperationQueue} to add
|
|
* FlatUIImplementation-specific methods that need to run in UI thread.
|
|
*/
|
|
/* package */ final class FlatUIViewOperationQueue extends UIViewOperationQueue {
|
|
|
|
private static final int[] MEASURE_BUFFER = new int[4];
|
|
|
|
private final FlatNativeViewHierarchyManager mNativeViewHierarchyManager;
|
|
private final ProcessLayoutRequests mProcessLayoutRequests = new ProcessLayoutRequests();
|
|
|
|
private final class ProcessLayoutRequests implements UIOperation {
|
|
@Override
|
|
public void execute() {
|
|
FlatViewGroup.processLayoutRequests();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* UIOperation that updates DrawCommands for a View defined by reactTag.
|
|
*/
|
|
private final class UpdateMountState implements UIOperation {
|
|
|
|
private final int mReactTag;
|
|
private final @Nullable DrawCommand[] mDrawCommands;
|
|
private final @Nullable AttachDetachListener[] mAttachDetachListeners;
|
|
private final @Nullable NodeRegion[] mNodeRegions;
|
|
|
|
private UpdateMountState(
|
|
int reactTag,
|
|
@Nullable DrawCommand[] drawCommands,
|
|
@Nullable AttachDetachListener[] listeners,
|
|
@Nullable NodeRegion[] nodeRegions) {
|
|
mReactTag = reactTag;
|
|
mDrawCommands = drawCommands;
|
|
mAttachDetachListeners = listeners;
|
|
mNodeRegions = nodeRegions;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.updateMountState(
|
|
mReactTag,
|
|
mDrawCommands,
|
|
mAttachDetachListeners,
|
|
mNodeRegions);
|
|
}
|
|
}
|
|
|
|
private final class UpdateViewGroup implements UIOperation {
|
|
|
|
private final int mReactTag;
|
|
private final int[] mViewsToAdd;
|
|
private final int[] mViewsToDetach;
|
|
|
|
private UpdateViewGroup(int reactTag, int[] viewsToAdd, int[] viewsToDetach) {
|
|
mReactTag = reactTag;
|
|
mViewsToAdd = viewsToAdd;
|
|
mViewsToDetach = viewsToDetach;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.updateViewGroup(mReactTag, mViewsToAdd, mViewsToDetach);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* UIOperation that updates View bounds for a View defined by reactTag.
|
|
*/
|
|
public final class UpdateViewBounds implements UIOperation {
|
|
|
|
private final int mReactTag;
|
|
private final int mLeft;
|
|
private final int mTop;
|
|
private final int mRight;
|
|
private final int mBottom;
|
|
|
|
private UpdateViewBounds(int reactTag, int left, int top, int right, int bottom) {
|
|
mReactTag = reactTag;
|
|
mLeft = left;
|
|
mTop = top;
|
|
mRight = right;
|
|
mBottom = bottom;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.updateViewBounds(mReactTag, mLeft, mTop, mRight, mBottom);
|
|
}
|
|
}
|
|
|
|
private final class SetPadding implements UIOperation {
|
|
|
|
private final int mReactTag;
|
|
private final int mPaddingLeft;
|
|
private final int mPaddingTop;
|
|
private final int mPaddingRight;
|
|
private final int mPaddingBottom;
|
|
|
|
private SetPadding(
|
|
int reactTag,
|
|
int paddingLeft,
|
|
int paddingTop,
|
|
int paddingRight,
|
|
int paddingBottom) {
|
|
mReactTag = reactTag;
|
|
mPaddingLeft = paddingLeft;
|
|
mPaddingTop = paddingTop;
|
|
mPaddingRight = paddingRight;
|
|
mPaddingBottom = paddingBottom;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.setPadding(
|
|
mReactTag,
|
|
mPaddingLeft,
|
|
mPaddingTop,
|
|
mPaddingRight,
|
|
mPaddingBottom);
|
|
}
|
|
}
|
|
|
|
private final class DropViews implements UIOperation {
|
|
|
|
private final int[] mViewsToDrop;
|
|
|
|
private DropViews(int[] viewsToDrop) {
|
|
mViewsToDrop = viewsToDrop;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.dropViews(mViewsToDrop);
|
|
}
|
|
}
|
|
|
|
private final class MeasureVirtualView implements UIOperation {
|
|
|
|
private final int mReactTag;
|
|
private final float mScaledX;
|
|
private final float mScaledY;
|
|
private final float mScaledWidth;
|
|
private final float mScaledHeight;
|
|
private final Callback mCallback;
|
|
|
|
private MeasureVirtualView(
|
|
int reactTag,
|
|
float scaledX,
|
|
float scaledY,
|
|
float scaledWidth,
|
|
float scaledHeight,
|
|
Callback callback) {
|
|
mReactTag = reactTag;
|
|
mScaledX = scaledX;
|
|
mScaledY = scaledY;
|
|
mScaledWidth = scaledWidth;
|
|
mScaledHeight = scaledHeight;
|
|
mCallback = callback;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
// Measure native View
|
|
mNativeViewHierarchyManager.measure(mReactTag, MEASURE_BUFFER);
|
|
|
|
float nativeViewX = MEASURE_BUFFER[0];
|
|
float nativeViewY = MEASURE_BUFFER[1];
|
|
float nativeViewWidth = MEASURE_BUFFER[2];
|
|
float nativeViewHeight = MEASURE_BUFFER[3];
|
|
|
|
// Calculate size of the virtual child inside native View.
|
|
float x = PixelUtil.toDIPFromPixel(mScaledX * nativeViewWidth + nativeViewX);
|
|
float y = PixelUtil.toDIPFromPixel(mScaledY * nativeViewHeight + nativeViewY);
|
|
float width = PixelUtil.toDIPFromPixel(mScaledWidth * nativeViewWidth);
|
|
float height = PixelUtil.toDIPFromPixel(mScaledHeight * nativeViewHeight);
|
|
|
|
mCallback.invoke(0, 0, width, height, x, y);
|
|
}
|
|
}
|
|
|
|
public final class DetachAllChildrenFromViews implements UIViewOperationQueue.UIOperation {
|
|
private @Nullable int[] mViewsToDetachAllChildrenFrom;
|
|
|
|
public void setViewsToDetachAllChildrenFrom(int[] viewsToDetachAllChildrenFrom) {
|
|
mViewsToDetachAllChildrenFrom = viewsToDetachAllChildrenFrom;
|
|
}
|
|
|
|
@Override
|
|
public void execute() {
|
|
mNativeViewHierarchyManager.detachAllChildrenFromViews(mViewsToDetachAllChildrenFrom);
|
|
}
|
|
}
|
|
|
|
public FlatUIViewOperationQueue(
|
|
ReactApplicationContext reactContext,
|
|
FlatNativeViewHierarchyManager nativeViewHierarchyManager) {
|
|
super(reactContext, nativeViewHierarchyManager);
|
|
|
|
mNativeViewHierarchyManager = nativeViewHierarchyManager;
|
|
}
|
|
|
|
/**
|
|
* Enqueues a new UIOperation that will update DrawCommands for a View defined by reactTag.
|
|
*/
|
|
public void enqueueUpdateMountState(
|
|
int reactTag,
|
|
@Nullable DrawCommand[] drawCommands,
|
|
@Nullable AttachDetachListener[] listeners,
|
|
@Nullable NodeRegion[] nodeRegions) {
|
|
enqueueUIOperation(new UpdateMountState(reactTag, drawCommands, listeners, nodeRegions));
|
|
}
|
|
|
|
public void enqueueUpdateViewGroup(int reactTag, int[] viewsToAdd, int[] viewsToDetach) {
|
|
enqueueUIOperation(new UpdateViewGroup(reactTag, viewsToAdd, viewsToDetach));
|
|
}
|
|
|
|
public UpdateViewBounds createUpdateViewBounds(
|
|
int reactTag,
|
|
int left,
|
|
int top,
|
|
int right,
|
|
int bottom) {
|
|
return new UpdateViewBounds(reactTag, left, top, right, bottom);
|
|
}
|
|
|
|
/**
|
|
* Enqueues a new UIOperation that will update View bounds for a View defined by reactTag.
|
|
*/
|
|
public void enqueueUpdateViewBounds(UpdateViewBounds updateViewBounds) {
|
|
enqueueUIOperation(updateViewBounds);
|
|
}
|
|
|
|
public void enqueueSetPadding(
|
|
int reactTag,
|
|
int paddingLeft,
|
|
int paddingTop,
|
|
int paddingRight,
|
|
int paddingBottom) {
|
|
enqueueUIOperation(
|
|
new SetPadding(reactTag, paddingLeft, paddingTop, paddingRight, paddingBottom));
|
|
}
|
|
|
|
public void enqueueDropViews(int[] viewsToDrop) {
|
|
enqueueUIOperation(new DropViews(viewsToDrop));
|
|
}
|
|
|
|
public void enqueueMeasureVirtualView(
|
|
int reactTag,
|
|
float scaledX,
|
|
float scaledY,
|
|
float scaledWidth,
|
|
float scaledHeight,
|
|
Callback callback) {
|
|
enqueueUIOperation(new MeasureVirtualView(
|
|
reactTag,
|
|
scaledX,
|
|
scaledY,
|
|
scaledWidth,
|
|
scaledHeight,
|
|
callback));
|
|
}
|
|
|
|
public void enqueueProcessLayoutRequests() {
|
|
enqueueUIOperation(mProcessLayoutRequests);
|
|
}
|
|
|
|
public DetachAllChildrenFromViews enqueueDetachAllChildrenFromViews() {
|
|
DetachAllChildrenFromViews op = new DetachAllChildrenFromViews();
|
|
enqueueUIOperation(op);
|
|
return op;
|
|
}
|
|
}
|