Allow nesting React-Native View components inside svg (Android, poc wip)

This commit is contained in:
Mikael Sand
2018-02-21 16:50:04 +02:00
parent b5eeb1ee72
commit f7b195a5a0
5 changed files with 44 additions and 12 deletions
@@ -96,6 +96,8 @@ class GroupShadowNode extends RenderableShadowNode {
} else if (lNode instanceof SvgViewShadowNode) {
SvgViewShadowNode svgView = (SvgViewShadowNode)lNode;
svgView.drawChildren(canvas);
} else {
lNode.calculateLayout();
}
}
});
@@ -16,22 +16,26 @@ import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ReactShadowNodeImpl;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.TouchEvent;
import com.facebook.react.uimanager.events.TouchEventCoalescingKeyHelper;
import com.facebook.react.uimanager.events.TouchEventType;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.view.ReactViewGroup;
import javax.annotation.Nullable;
/**
* Custom {@link View} implementation that draws an RNSVGSvg React view and its \childrn.
* Custom {@link View} implementation that draws an RNSVGSvg React view and its children.
*/
@SuppressLint("ViewConstructor")
public class SvgView extends View {
public class SvgView extends ViewGroup {
public enum Events {
@SuppressWarnings("unused")
EVENT_DATA_URL("onDataURL");
@@ -100,6 +104,30 @@ public class SvgView extends View {
return super.dispatchTouchEvent(ev);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < this.getChildCount(); i++) {
View child = this.getChildAt(i);
if (child instanceof ReactViewGroup) {
ReactShadowNodeImpl node = getShadowNode();
for (int j = 0; j < node.getChildCount(); j++) {
ReactShadowNodeImpl nodeChild = node.getChildAt(j);
if (nodeChild.getReactTag() != child.getId()) {
continue;
}
float x = nodeChild.getLayoutX();
float y = nodeChild.getLayoutY();
float nr = x + nodeChild.getLayoutWidth();
float nb = y + nodeChild.getLayoutHeight();
child.layout(Math.round(x), Math.round(y), Math.round(nr), Math.round(nb));
break;
}
}
}
}
private int getAbsoluteLeft(View view) {
int left = view.getLeft() - view.getScrollX();
@@ -12,6 +12,7 @@ package com.horcrux.svg;
import android.graphics.Bitmap;
import android.util.SparseArray;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaNode;
@@ -24,7 +25,7 @@ import javax.annotation.Nullable;
* ViewManager for RNSVGSvgView React views. Renders as a {@link SvgView} and handles
* invalidating the native view on shadow view updates happening in the underlying tree.
*/
class SvgViewManager extends BaseViewManager<SvgView, SvgViewShadowNode> {
class SvgViewManager extends ViewGroupManager<SvgView> {
private static final String REACT_CLASS = "RNSVGSvgView";
@@ -18,6 +18,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.Base64;
import android.view.View;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.LayoutShadowNode;
@@ -110,7 +111,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
@Override
public boolean isVirtualAnchor() {
return true;
return false;
}
@Override
@@ -185,6 +186,8 @@ public class SvgViewShadowNode extends LayoutShadowNode {
if (node.isResponsible() && !mResponsible) {
mResponsible = true;
}
} else {
lNode.calculateLayout();
}
}
});
@@ -262,10 +265,6 @@ public class SvgViewShadowNode extends LayoutShadowNode {
void traverseChildren(VirtualNode.NodeRunnable runner) {
for (int i = 0; i < getChildCount(); i++) {
ReactShadowNode child = getChildAt(i);
if (!(child instanceof VirtualNode)) {
continue;
}
runner.run((LayoutShadowNode) child);
}
}
@@ -64,6 +64,7 @@ abstract class VirtualNode extends LayoutShadowNode {
private GlyphContext glyphContext;
VirtualNode() {
setIsLayoutOnly(true);
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
}
@@ -72,6 +73,11 @@ abstract class VirtualNode extends LayoutShadowNode {
return true;
}
@Override
public boolean isVirtualAnchor() {
return true;
}
@Nullable
GroupShadowNode getTextRoot() {
VirtualNode node = this;
@@ -314,10 +320,6 @@ abstract class VirtualNode extends LayoutShadowNode {
void traverseChildren(NodeRunnable runner) {
for (int i = 0; i < getChildCount(); i++) {
ReactShadowNode child = getChildAt(i);
if (!(child instanceof VirtualNode) && !(child instanceof SvgViewShadowNode)) {
continue;
}
runner.run((LayoutShadowNode) child);
}
}