mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-15 23:03:58 +08:00
Add backward compatible support for onLayout event in Fabric
Reviewed By: achen1 Differential Revision: D8231722 fbshipit-source-id: 3d0641a7813e742ca81b98576f9ffc30ee597f30
This commit is contained in:
committed by
Facebook Github Bot
parent
6c989fe7c6
commit
6aea98441a
@@ -10,6 +10,7 @@ package com.facebook.react.fabric;
|
||||
import static android.view.View.MeasureSpec.AT_MOST;
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.UNSPECIFIED;
|
||||
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -24,9 +25,11 @@ import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.fabric.events.FabricEventEmitter;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||
import com.facebook.react.uimanager.OnLayoutEvent;
|
||||
import com.facebook.react.uimanager.ReactRootViewTagGenerator;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.ReactShadowNodeImpl;
|
||||
@@ -37,6 +40,7 @@ import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||
import com.facebook.react.uimanager.common.MeasureSpecProvider;
|
||||
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
@@ -61,13 +65,15 @@ public class FabricUIManager implements UIManager, JSHandler {
|
||||
private final JavaScriptContextHolder mJSContext;
|
||||
private volatile int mCurrentBatch = 0;
|
||||
private final FabricReconciler mFabricReconciler;
|
||||
private final EventDispatcher mEventDispatcher;
|
||||
private FabricBinding mBinding;
|
||||
private long mEventHandlerPointer;
|
||||
|
||||
public FabricUIManager(
|
||||
ReactApplicationContext reactContext,
|
||||
ViewManagerRegistry viewManagerRegistry,
|
||||
JavaScriptContextHolder jsContext) {
|
||||
JavaScriptContextHolder jsContext,
|
||||
EventDispatcher eventDispatcher) {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
||||
mReactApplicationContext = reactContext;
|
||||
mViewManagerRegistry = viewManagerRegistry;
|
||||
@@ -76,7 +82,12 @@ public class FabricUIManager implements UIManager, JSHandler {
|
||||
new UIViewOperationQueue(
|
||||
reactContext, mNativeViewHierarchyManager, 0);
|
||||
mFabricReconciler = new FabricReconciler(mUIViewOperationQueue);
|
||||
mEventDispatcher = eventDispatcher;
|
||||
mJSContext = jsContext;
|
||||
|
||||
FabricEventEmitter eventEmitter =
|
||||
new FabricEventEmitter(reactContext, this);
|
||||
eventDispatcher.registerEventEmitter(FABRIC, eventEmitter);
|
||||
}
|
||||
|
||||
public void setBinding(FabricBinding binding) {
|
||||
@@ -355,7 +366,18 @@ public class FabricUIManager implements UIManager, JSHandler {
|
||||
if (mRootShadowNodeRegistry.getNode(tag) == null) {
|
||||
boolean frameDidChange =
|
||||
node.dispatchUpdates(absoluteX, absoluteY, mUIViewOperationQueue, null);
|
||||
// Notify JS about layout event if requested
|
||||
// and if the position or dimensions actually changed
|
||||
// (consistent with iOS and Android Default implementation).
|
||||
if (frameDidChange && node.shouldNotifyOnLayout()) {
|
||||
mUIViewOperationQueue.enqueueOnLayoutEvent(tag,
|
||||
node.getScreenX(),
|
||||
node.getScreenY(),
|
||||
node.getScreenWidth(),
|
||||
node.getScreenHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// Set the reference to the OriginalReactShadowNode to NULL, as the tree is already committed
|
||||
// and we do not need to hold references to the previous tree anymore
|
||||
node.setOriginalReactShadowNode(null);
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.fabric.FabricUIManager;
|
||||
import com.facebook.react.fabric.Scheduler;
|
||||
import com.facebook.react.fabric.Work;
|
||||
import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
@@ -48,9 +49,13 @@ public class FabricEventEmitter implements RCTEventEmitter, Closeable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap params) {
|
||||
long eventTarget = mFabricUIManager.createEventTarget(targetTag);
|
||||
mScheduler.scheduleWork(new FabricUIManagerWork(eventTarget, eventName, params));
|
||||
public void receiveEvent(int reactTag, String eventName, @Nullable WritableMap params) {
|
||||
try {
|
||||
long eventTarget = mFabricUIManager.createEventTarget(reactTag);
|
||||
mScheduler.scheduleWork(new FabricUIManagerWork(eventTarget, eventName, params));
|
||||
} catch (IllegalViewOperationException e) {
|
||||
Log.e(TAG, "Unable to emmit event for tag " + reactTag, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -224,11 +224,11 @@ public class NativeViewHierarchyManager {
|
||||
public long getInstanceHandle(int reactTag) {
|
||||
View view = mTagsToViews.get(reactTag);
|
||||
if (view == null) {
|
||||
throw new IllegalArgumentException("Unable to find view for tag: " + reactTag);
|
||||
throw new IllegalViewOperationException("Unable to find view for tag: " + reactTag);
|
||||
}
|
||||
Long instanceHandle = (Long) view.getTag(R.id.view_tag_instance_handle);
|
||||
if (instanceHandle == null) {
|
||||
throw new IllegalArgumentException("Unable to find instanceHandle for tag: " + reactTag);
|
||||
throw new IllegalViewOperationException("Unable to find instanceHandle for tag: " + reactTag);
|
||||
}
|
||||
return instanceHandle;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,38 @@ public class UIViewOperationQueue {
|
||||
}
|
||||
}
|
||||
|
||||
private final class EmitOnLayoutEventOperation extends ViewOperation {
|
||||
|
||||
private final int mScreenX;
|
||||
private final int mScreenY;
|
||||
private final int mScreenWidth;
|
||||
private final int mScreenHeight;
|
||||
|
||||
public EmitOnLayoutEventOperation(
|
||||
int tag,
|
||||
int screenX,
|
||||
int screenY,
|
||||
int screenWidth,
|
||||
int screenHeight) {
|
||||
super(tag);
|
||||
mScreenX = screenX;
|
||||
mScreenY = screenY;
|
||||
mScreenWidth = screenWidth;
|
||||
mScreenHeight = screenHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
mReactApplicationContext.getNativeModule(UIManagerModule.class)
|
||||
.getEventDispatcher()
|
||||
.dispatchEvent(OnLayoutEvent.obtain(
|
||||
mTag,
|
||||
mScreenX,
|
||||
mScreenY,
|
||||
mScreenWidth,
|
||||
mScreenHeight));
|
||||
}
|
||||
}
|
||||
|
||||
private final class UpdateInstanceHandleOperation extends ViewOperation {
|
||||
|
||||
@@ -706,6 +738,16 @@ public class UIViewOperationQueue {
|
||||
mOperations.add(new UpdatePropertiesOperation(reactTag, props));
|
||||
}
|
||||
|
||||
public void enqueueOnLayoutEvent(
|
||||
int tag,
|
||||
int screenX,
|
||||
int screenY,
|
||||
int screenWidth,
|
||||
int screenHeight) {
|
||||
mOperations.add(new EmitOnLayoutEventOperation(tag, screenX, screenY, screenWidth, screenHeight));
|
||||
}
|
||||
|
||||
|
||||
public void enqueueUpdateLayout(
|
||||
int parentTag,
|
||||
int reactTag,
|
||||
|
||||
Reference in New Issue
Block a user