mirror of
https://github.com/status-im/react-native.git
synced 2025-01-16 20:44:10 +00:00
Add support for custom AndroidViews
Summary: This diff adds an `AndroidView` as a proxy for custom Views in FlatUIImplementation. Any ReactShadowNode that FlatUIImplementation doesn't recognize (because they don't extend from FlatShadowNode) will be wrapped with AndroidView to ensure that it measures and displays correctly. While not perfect, this is the easiest way to support custom Views (EditTexts, DrawerLayouts, ScrollViews etc). Reviewed By: ahmedre Differential Revision: D2751716
This commit is contained in:
parent
1da7049426
commit
dbe9cc333c
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* 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 com.facebook.csslayout.CSSNode;
|
||||||
|
import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
final ViewManager mViewManager;
|
||||||
|
private final ReactShadowNode mReactShadowNode;
|
||||||
|
private final boolean mNeedsCustomLayoutForChildren;
|
||||||
|
|
||||||
|
/* package */ AndroidView(ViewManager viewManager) {
|
||||||
|
mViewManager = 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ boolean needsCustomLayoutForChildren() {
|
||||||
|
return mNeedsCustomLayoutForChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(CatalystStylesDiffMap styles) {
|
||||||
|
if (mReactShadowNode != null) {
|
||||||
|
mReactShadowNode.updateProperties(styles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChildAt(CSSNode child, int i) {
|
||||||
|
super.addChildAt(child, i);
|
||||||
|
((FlatShadowNode) child).forceMountToView();
|
||||||
|
}
|
||||||
|
}
|
@ -13,10 +13,12 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.MeasureSpec;
|
import android.view.View.MeasureSpec;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||||
import com.facebook.react.uimanager.SizeMonitoringFrameLayout;
|
import com.facebook.react.uimanager.SizeMonitoringFrameLayout;
|
||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
|
import com.facebook.react.uimanager.ViewGroupManager;
|
||||||
import com.facebook.react.uimanager.ViewManagerRegistry;
|
import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,8 +73,18 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void updateViewGroup(int reactTag, int[] viewsToAdd, int[] viewsToDetach) {
|
/* package */ void updateViewGroup(int reactTag, int[] viewsToAdd, int[] viewsToDetach) {
|
||||||
FlatViewGroup view = (FlatViewGroup) resolveView(reactTag);
|
View view = resolveView(reactTag);
|
||||||
view.mountViews(this, viewsToAdd, viewsToDetach);
|
if (view instanceof FlatViewGroup) {
|
||||||
|
((FlatViewGroup) view).mountViews(this, viewsToAdd, viewsToDetach);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup viewGroup = (ViewGroup) view;
|
||||||
|
ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(reactTag);
|
||||||
|
for (int i = 0; i < viewsToAdd.length; ++i) {
|
||||||
|
int tag = Math.abs(viewsToAdd[i]);
|
||||||
|
viewManager.addView(viewGroup, resolveView(tag), i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,8 +115,17 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
|
|||||||
|
|
||||||
/* package */ void detachAllChildrenFromViews(int[] viewsToDetachAllChildrenFrom) {
|
/* package */ void detachAllChildrenFromViews(int[] viewsToDetachAllChildrenFrom) {
|
||||||
for (int viewTag : viewsToDetachAllChildrenFrom) {
|
for (int viewTag : viewsToDetachAllChildrenFrom) {
|
||||||
FlatViewGroup viewGroup = (FlatViewGroup) resolveView(viewTag);
|
View view = resolveView(viewTag);
|
||||||
viewGroup.detachAllViewsFromParent();
|
if (view instanceof FlatViewGroup) {
|
||||||
|
((FlatViewGroup) view).detachAllViewsFromParent();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup viewGroup = (ViewGroup) view;
|
||||||
|
ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(viewTag);
|
||||||
|
for (int i = viewManager.getChildCount(viewGroup) - 1; i >= 0; --i) {
|
||||||
|
viewManager.removeViewAt(viewGroup, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,16 @@ public class FlatUIImplementation extends UIImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
protected ReactShadowNode createShadowNode(String className) {
|
||||||
|
ReactShadowNode cssNode = super.createShadowNode(className);
|
||||||
|
if (cssNode instanceof FlatShadowNode) {
|
||||||
|
return cssNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewManager viewManager = resolveViewManager(className);
|
||||||
|
return new AndroidView(viewManager);
|
||||||
|
}
|
||||||
|
|
||||||
protected void handleCreateView(
|
protected void handleCreateView(
|
||||||
ReactShadowNode cssNode,
|
ReactShadowNode cssNode,
|
||||||
int rootViewTag,
|
int rootViewTag,
|
||||||
|
@ -149,7 +149,14 @@ import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
|||||||
mNodeRegions.start(node.getNodeRegions());
|
mNodeRegions.start(node.getNodeRegions());
|
||||||
mNativeChildren.start(node.getNativeChildren());
|
mNativeChildren.start(node.getNativeChildren());
|
||||||
|
|
||||||
collectStateRecursively(node, 0, 0, width, height);
|
boolean isAndroidView = false;
|
||||||
|
boolean needsCustomLayoutForChildren = false;
|
||||||
|
if (node instanceof AndroidView) {
|
||||||
|
isAndroidView = true;
|
||||||
|
needsCustomLayoutForChildren = ((AndroidView) node).needsCustomLayoutForChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
collectStateRecursively(node, 0, 0, width, height, isAndroidView, needsCustomLayoutForChildren);
|
||||||
|
|
||||||
boolean shouldUpdateMountState = false;
|
boolean shouldUpdateMountState = false;
|
||||||
final DrawCommand[] drawCommands = mDrawCommands.finish();
|
final DrawCommand[] drawCommands = mDrawCommands.finish();
|
||||||
@ -248,7 +255,9 @@ import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
|||||||
float left,
|
float left,
|
||||||
float top,
|
float top,
|
||||||
float right,
|
float right,
|
||||||
float bottom) {
|
float bottom,
|
||||||
|
boolean isAndroidView,
|
||||||
|
boolean needsCustomLayoutForChildren) {
|
||||||
if (node.hasNewLayout()) {
|
if (node.hasNewLayout()) {
|
||||||
node.markLayoutSeen();
|
node.markLayoutSeen();
|
||||||
}
|
}
|
||||||
@ -257,7 +266,7 @@ import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
|||||||
|
|
||||||
for (int i = 0, childCount = node.getChildCount(); i != childCount; ++i) {
|
for (int i = 0, childCount = node.getChildCount(); i != childCount; ++i) {
|
||||||
FlatShadowNode child = (FlatShadowNode) node.getChildAt(i);
|
FlatShadowNode child = (FlatShadowNode) node.getChildAt(i);
|
||||||
processNodeAndCollectState(child, left, top);
|
processNodeAndCollectState(child, left, top, isAndroidView, needsCustomLayoutForChildren);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +276,9 @@ import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
|||||||
private void processNodeAndCollectState(
|
private void processNodeAndCollectState(
|
||||||
FlatShadowNode node,
|
FlatShadowNode node,
|
||||||
float parentLeft,
|
float parentLeft,
|
||||||
float parentTop) {
|
float parentTop,
|
||||||
|
boolean parentIsAndroidView,
|
||||||
|
boolean needsCustomLayout) {
|
||||||
int tag = node.getReactTag();
|
int tag = node.getReactTag();
|
||||||
|
|
||||||
float width = node.getLayoutWidth();
|
float width = node.getLayoutWidth();
|
||||||
@ -284,12 +295,17 @@ import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
|||||||
ensureBackingViewIsCreated(node, tag, null);
|
ensureBackingViewIsCreated(node, tag, null);
|
||||||
|
|
||||||
addNativeChild(node);
|
addNativeChild(node);
|
||||||
mDrawCommands.add(DrawView.INSTANCE);
|
if (!parentIsAndroidView) {
|
||||||
|
mDrawCommands.add(DrawView.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
collectStateForMountableNode(node, tag, width, height);
|
collectStateForMountableNode(node, tag, width, height);
|
||||||
mViewsToUpdateBounds.add(node);
|
|
||||||
|
if (!needsCustomLayout) {
|
||||||
|
mViewsToUpdateBounds.add(node);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
collectStateRecursively(node, left, top, right, bottom);
|
collectStateRecursively(node, left, top, right, bottom, false, false);
|
||||||
addNodeRegion(node.getNodeRegion());
|
addNodeRegion(node.getNodeRegion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user