mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-29 12:45:37 +08:00
Make AndroidView an interface
Summary: The current AndroidView stipulates that the backing shadow node can't be a FlatShadowNode. In some cases, however, we want to apply some of the same logic (ex not adding NodeRegions, etc) to other ViewManagers that have a FlatShadowNode backing (and that don't necessarily create a FlatViewGroup). This commit renames AndroidView to NativeViewWrapper, and re-introduces AndroidView as an interface, so that logic for padding, NodeRegions, etc can be shared. Differential Revision: D2942387
This commit is contained in:
@@ -9,86 +9,29 @@
|
|||||||
|
|
||||||
package com.facebook.react.flat;
|
package com.facebook.react.flat;
|
||||||
|
|
||||||
import com.facebook.csslayout.CSSNode;
|
import com.facebook.csslayout.Spacing;
|
||||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
|
||||||
import com.facebook.react.uimanager.ReactShadowNode;
|
|
||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
|
||||||
import com.facebook.react.uimanager.ViewGroupManager;
|
|
||||||
import com.facebook.react.uimanager.ViewManager;
|
|
||||||
|
|
||||||
/* package */ final class AndroidView extends FlatShadowNode {
|
interface AndroidView {
|
||||||
|
|
||||||
final ViewManager mViewManager;
|
/**
|
||||||
private final ReactShadowNode mReactShadowNode;
|
* Whether or not custom layout is needed for the children
|
||||||
private final boolean mNeedsCustomLayoutForChildren;
|
* @return a boolean representing whether custom layout is needed
|
||||||
private boolean mPaddingChanged = false;
|
*/
|
||||||
|
boolean needsCustomLayoutForChildren();
|
||||||
|
|
||||||
/* package */ AndroidView(ViewManager viewManager) {
|
/**
|
||||||
mViewManager = viewManager;
|
* Did the padding change
|
||||||
ReactShadowNode reactShadowNode = viewManager.createShadowNodeInstance();
|
* @return a boolean representing whether the padding changed
|
||||||
if (reactShadowNode instanceof CSSNode.MeasureFunction) {
|
*/
|
||||||
mReactShadowNode = reactShadowNode;
|
boolean isPaddingChanged();
|
||||||
setMeasureFunction((CSSNode.MeasureFunction) reactShadowNode);
|
|
||||||
} else {
|
|
||||||
mReactShadowNode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (viewManager instanceof ViewGroupManager) {
|
/**
|
||||||
ViewGroupManager viewGroupManager = (ViewGroupManager) viewManager;
|
* Reset the padding changed internal state
|
||||||
mNeedsCustomLayoutForChildren = viewGroupManager.needsCustomLayoutForChildren();
|
*/
|
||||||
} else {
|
void resetPaddingChanged();
|
||||||
mNeedsCustomLayoutForChildren = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
forceMountToView();
|
/**
|
||||||
}
|
* Get this node's padding, as defined by style + default padding.
|
||||||
|
*/
|
||||||
/* package */ boolean needsCustomLayoutForChildren() {
|
Spacing getPadding();
|
||||||
return mNeedsCustomLayoutForChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ boolean isPaddingChanged() {
|
|
||||||
return mPaddingChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ void resetPaddingChanged() {
|
|
||||||
mPaddingChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBackgroundColor(int backgroundColor) {
|
|
||||||
// suppress, this is handled by a ViewManager
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setThemedContext(ThemedReactContext themedContext) {
|
|
||||||
super.setThemedContext(themedContext);
|
|
||||||
|
|
||||||
if (mReactShadowNode != null) {
|
|
||||||
mReactShadowNode.setThemedContext(themedContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/* package*/ void handleUpdateProperties(ReactStylesDiffMap styles) {
|
|
||||||
if (mReactShadowNode != null) {
|
|
||||||
mReactShadowNode.updateProperties(styles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addChildAt(CSSNode child, int i) {
|
|
||||||
super.addChildAt(child, i);
|
|
||||||
if (child instanceof FlatShadowNode) {
|
|
||||||
((FlatShadowNode) child).forceMountToView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPadding(int spacingType, float padding) {
|
|
||||||
if (getPadding().set(spacingType, padding)) {
|
|
||||||
mPaddingChanged = true;
|
|
||||||
dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class FlatUIImplementation extends UIImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ViewManager viewManager = resolveViewManager(className);
|
ViewManager viewManager = resolveViewManager(className);
|
||||||
return new AndroidView(viewManager);
|
return new NativeViewWrapper(viewManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 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.csslayout.CSSNode;
|
||||||
|
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||||
|
import com.facebook.react.uimanager.ReactShadowNode;
|
||||||
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
|
import com.facebook.react.uimanager.ViewGroupManager;
|
||||||
|
import com.facebook.react.uimanager.ViewManager;
|
||||||
|
|
||||||
|
/* package */ final class NativeViewWrapper extends FlatShadowNode implements AndroidView {
|
||||||
|
|
||||||
|
@Nullable private final ReactShadowNode mReactShadowNode;
|
||||||
|
private final boolean mNeedsCustomLayoutForChildren;
|
||||||
|
private boolean mPaddingChanged = false;
|
||||||
|
|
||||||
|
/* package */ NativeViewWrapper(ViewManager viewManager) {
|
||||||
|
ReactShadowNode reactShadowNode = viewManager.createShadowNodeInstance();
|
||||||
|
if (reactShadowNode instanceof CSSNode.MeasureFunction) {
|
||||||
|
mReactShadowNode = reactShadowNode;
|
||||||
|
setMeasureFunction((CSSNode.MeasureFunction) reactShadowNode);
|
||||||
|
} else {
|
||||||
|
mReactShadowNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewManager instanceof ViewGroupManager) {
|
||||||
|
ViewGroupManager viewGroupManager = (ViewGroupManager) viewManager;
|
||||||
|
mNeedsCustomLayoutForChildren = viewGroupManager.needsCustomLayoutForChildren();
|
||||||
|
} else {
|
||||||
|
mNeedsCustomLayoutForChildren = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceMountToView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean needsCustomLayoutForChildren() {
|
||||||
|
return mNeedsCustomLayoutForChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPaddingChanged() {
|
||||||
|
return mPaddingChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetPaddingChanged() {
|
||||||
|
mPaddingChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBackgroundColor(int backgroundColor) {
|
||||||
|
// suppress, this is handled by a ViewManager
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setThemedContext(ThemedReactContext themedContext) {
|
||||||
|
super.setThemedContext(themedContext);
|
||||||
|
|
||||||
|
if (mReactShadowNode != null) {
|
||||||
|
mReactShadowNode.setThemedContext(themedContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/* package*/ void handleUpdateProperties(ReactStylesDiffMap styles) {
|
||||||
|
if (mReactShadowNode != null) {
|
||||||
|
mReactShadowNode.updateProperties(styles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChildAt(CSSNode child, int i) {
|
||||||
|
super.addChildAt(child, i);
|
||||||
|
if (child instanceof FlatShadowNode) {
|
||||||
|
((FlatShadowNode) child).forceMountToView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPadding(int spacingType, float padding) {
|
||||||
|
if (getPadding().set(spacingType, padding)) {
|
||||||
|
mPaddingChanged = true;
|
||||||
|
dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,20 +9,17 @@
|
|||||||
|
|
||||||
package com.facebook.react.flat;
|
package com.facebook.react.flat;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
|
||||||
import com.facebook.csslayout.Spacing;
|
|
||||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
import com.facebook.react.views.text.ReactTextUpdate;
|
import com.facebook.react.views.text.ReactTextUpdate;
|
||||||
|
|
||||||
import static com.facebook.react.views.text.ReactTextShadowNode.UNSET;
|
import static com.facebook.react.views.text.ReactTextShadowNode.UNSET;
|
||||||
|
|
||||||
public class RCTTextInput extends RCTVirtualText {
|
public class RCTTextInput extends RCTVirtualText implements AndroidView {
|
||||||
private int mJsEventCount = UNSET;
|
private int mJsEventCount = UNSET;
|
||||||
private @Nullable float[] mComputedPadding;
|
private boolean mPaddingChanged = false;
|
||||||
|
|
||||||
public RCTTextInput() {
|
public RCTTextInput() {
|
||||||
forceMountToView();
|
forceMountToView();
|
||||||
@@ -46,15 +43,11 @@ public class RCTTextInput extends RCTVirtualText {
|
|||||||
@Override
|
@Override
|
||||||
public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
|
public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
|
||||||
super.onCollectExtraUpdates(uiViewOperationQueue);
|
super.onCollectExtraUpdates(uiViewOperationQueue);
|
||||||
|
if (mJsEventCount != UNSET) {
|
||||||
if (mComputedPadding != null) {
|
ReactTextUpdate reactTextUpdate =
|
||||||
uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), mComputedPadding);
|
new ReactTextUpdate(getText(), mJsEventCount, false);
|
||||||
mComputedPadding = null;
|
uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactTextUpdate reactTextUpdate =
|
|
||||||
new ReactTextUpdate(getText(), mJsEventCount, false);
|
|
||||||
uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "mostRecentEventCount")
|
@ReactProp(name = "mostRecentEventCount")
|
||||||
@@ -64,18 +57,20 @@ public class RCTTextInput extends RCTVirtualText {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPadding(int spacingType, float padding) {
|
public void setPadding(int spacingType, float padding) {
|
||||||
super.setPadding(spacingType, padding);
|
if (getPadding().set(spacingType, padding)) {
|
||||||
mComputedPadding = spacingToFloatArray(getPadding());
|
mPaddingChanged = true;
|
||||||
markUpdated();
|
dirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float[] spacingToFloatArray(Spacing spacing) {
|
@Override
|
||||||
return new float[] {
|
public boolean isPaddingChanged() {
|
||||||
spacing.get(Spacing.LEFT),
|
return mPaddingChanged;
|
||||||
spacing.get(Spacing.TOP),
|
}
|
||||||
spacing.get(Spacing.RIGHT),
|
|
||||||
spacing.get(Spacing.BOTTOM),
|
@Override
|
||||||
};
|
public void resetPaddingChanged() {
|
||||||
|
mPaddingChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,4 +82,9 @@ public class RCTTextInput extends RCTVirtualText {
|
|||||||
applySpans(sb);
|
applySpans(sb);
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean needsCustomLayoutForChildren() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,11 +240,7 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
|||||||
isAndroidView,
|
isAndroidView,
|
||||||
needsCustomLayoutForChildren);
|
needsCustomLayoutForChildren);
|
||||||
|
|
||||||
// this is a temporary measure to skip adding node regions for RCTTextInput. This will be fixed
|
if (!isAndroidView && node.isVirtualAnchor()) {
|
||||||
// in a patch soon which will convert AndroidView into an interface, thus allowing RCTTextInput
|
|
||||||
// to be treated as an AndroidView
|
|
||||||
boolean skipAddingNodeRegion = node instanceof RCTTextInput;
|
|
||||||
if (!isAndroidView && node.isVirtualAnchor() && !skipAddingNodeRegion) {
|
|
||||||
// If RCTText is mounted to View, virtual children will not receive any touch events
|
// If RCTText is mounted to View, virtual children will not receive any touch events
|
||||||
// because they don't get added to nodeRegions, so nodeRegions will be empty and
|
// because they don't get added to nodeRegions, so nodeRegions will be empty and
|
||||||
// FlatViewGroup.reactTagForTouch() will always return RCTText's id. To fix the issue,
|
// FlatViewGroup.reactTagForTouch() will always return RCTText's id. To fix the issue,
|
||||||
|
|||||||
Reference in New Issue
Block a user