diff --git a/doric-android/doric/src/main/java/pub/doric/Doric.java b/doric-android/doric/src/main/java/pub/doric/Doric.java index a17124fb..0993e996 100644 --- a/doric-android/doric/src/main/java/pub/doric/Doric.java +++ b/doric-android/doric/src/main/java/pub/doric/Doric.java @@ -17,6 +17,10 @@ package pub.doric; import android.app.Application; +import com.facebook.soloader.SoLoader; + +import java.io.IOException; + import pub.doric.loader.DoricJSLoaderManager; import pub.doric.loader.IDoricJSLoader; @@ -35,6 +39,11 @@ public class Doric { */ public static void init(Application application) { sApplication = application; + try { + SoLoader.init(application, 0); + } catch (IOException e) { + e.printStackTrace(); + } } public static Application application() { diff --git a/doric-android/doric/src/main/java/pub/doric/shader/ViewNode.java b/doric-android/doric/src/main/java/pub/doric/shader/ViewNode.java index 13d0b6bb..7cfe6d65 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/ViewNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/ViewNode.java @@ -37,6 +37,8 @@ import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import com.facebook.yoga.YogaNode; +import com.facebook.yoga.android.YogaLayout; import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSONBuilder; @@ -53,6 +55,7 @@ import pub.doric.DoricRegistry; import pub.doric.async.AsyncResult; import pub.doric.extension.bridge.DoricMethod; import pub.doric.extension.bridge.DoricPromise; +import pub.doric.shader.flex.FlexNode; import pub.doric.utils.DoricConstant; import pub.doric.utils.DoricContextHolder; import pub.doric.utils.DoricLog; @@ -70,6 +73,11 @@ public abstract class ViewNode extends DoricContextHolder { String mId; protected ViewGroup.LayoutParams mLayoutParams; private String mType; + private JSObject mFlexConfig; + + public JSObject getFlexConfig() { + return mFlexConfig; + } public ViewNode(DoricContext doricContext) { super(doricContext); @@ -435,6 +443,11 @@ public abstract class ViewNode extends DoricContextHolder { getNodeView().setVisibility(prop.asBoolean().value() ? View.GONE : View.VISIBLE); } break; + case "flexConfig": + if (prop.isObject()) { + mFlexConfig = prop.asObject(); + } + break; default: break; } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/flex/FlexNode.java b/doric-android/doric/src/main/java/pub/doric/shader/flex/FlexNode.java index bd3ec8f8..167251f0 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/flex/FlexNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/flex/FlexNode.java @@ -17,13 +17,26 @@ package pub.doric.shader.flex; import android.view.ViewGroup; +import com.facebook.yoga.YogaAlign; +import com.facebook.yoga.YogaDirection; +import com.facebook.yoga.YogaDisplay; +import com.facebook.yoga.YogaEdge; +import com.facebook.yoga.YogaFlexDirection; +import com.facebook.yoga.YogaJustify; +import com.facebook.yoga.YogaNode; +import com.facebook.yoga.YogaOverflow; +import com.facebook.yoga.YogaPositionType; +import com.facebook.yoga.YogaWrap; import com.facebook.yoga.android.YogaLayout; import com.github.pengfeizhou.jscore.JSObject; +import com.github.pengfeizhou.jscore.JSValue; import pub.doric.DoricContext; import pub.doric.extension.bridge.DoricPlugin; import pub.doric.shader.GroupNode; import pub.doric.shader.ViewNode; +import pub.doric.utils.DoricLog; +import pub.doric.utils.DoricUtils; /** * @Description: FlexBox Node @@ -32,6 +45,11 @@ import pub.doric.shader.ViewNode; */ @DoricPlugin(name = "FlexLayout") public class FlexNode extends GroupNode { + + private static final int FLEX_VALUE_TYPE_POINT = 1; + private static final int FLEX_VALUE_TYPE_PERCENT = 2; + private static final int FLEX_VALUE_TYPE_AUTO = 3; + public FlexNode(DoricContext doricContext) { super(doricContext); } @@ -51,4 +69,676 @@ public class FlexNode extends GroupNode { protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) { super.blendSubLayoutConfig(viewNode, jsObject); } + + @Override + protected void blend(YogaLayout view, String name, JSValue prop) { + if ("flexConfig".equals(name)) { + blendSubFlexConfig(mView.getYogaNode(), prop.asObject()); + } else { + super.blend(view, name, prop); + } + } + + @Override + public void blend(JSObject jsObject) { + super.blend(jsObject); + for (ViewNode childNode : mChildNodes) { + YogaNode yogaNode = this.mView.getYogaNodeForView(childNode.getNodeView()); + if (yogaNode != null) { + blendSubFlexConfig(yogaNode, childNode.getFlexConfig()); + } + } + } + + private void blendSubFlexConfig(YogaNode yogaNode, JSObject jsObject) { + if (jsObject == null) { + return; + } + for (String name : jsObject.propertySet()) { + JSValue value = jsObject.getProperty(name); + blendFlexConfig(yogaNode, name, value); + } + } + + private void blendFlexConfig(final YogaNode yogaNode, String name, JSValue value) { + switch (name) { + case "direction": + yogaNode.setDirection(YogaDirection.fromInt(value.asNumber().toInt())); + break; + case "flexDirection": + yogaNode.setFlexDirection(YogaFlexDirection.fromInt(value.asNumber().toInt())); + break; + case "justifyContent": + yogaNode.setJustifyContent(YogaJustify.fromInt(value.asNumber().toInt())); + break; + case "alignContent": + yogaNode.setAlignContent(YogaAlign.fromInt(value.asNumber().toInt())); + break; + case "alignItems": + yogaNode.setAlignItems(YogaAlign.fromInt(value.asNumber().toInt())); + break; + case "alignSelf": + yogaNode.setAlignSelf(YogaAlign.fromInt(value.asNumber().toInt())); + break; + case "positionType": + yogaNode.setPositionType(YogaPositionType.fromInt(value.asNumber().toInt())); + break; + case "flexWrap": + yogaNode.setWrap(YogaWrap.fromInt(value.asNumber().toInt())); + break; + case "overFlow": + yogaNode.setOverflow(YogaOverflow.fromInt(value.asNumber().toInt())); + break; + case "display": + yogaNode.setDisplay(YogaDisplay.fromInt(value.asNumber().toInt())); + break; + case "flex": + yogaNode.setFlex(value.asNumber().toFloat()); + break; + case "flexGrow": + yogaNode.setFlexGrow(value.asNumber().toFloat()); + break; + case "flexShrink": + yogaNode.setFlexShrink(value.asNumber().toFloat()); + break; + case "flexBasis": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setFlexBasis(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setFlexBasisPercent(v); + } + + @Override + public void setAuto() { + yogaNode.setFlexBasisAuto(); + } + }); + break; + case "marginLeft": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.LEFT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.LEFT, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.LEFT); + } + }); + break; + case "marginRight": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.RIGHT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.RIGHT, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.RIGHT); + } + }); + break; + case "marginTop": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.TOP, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.TOP, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.TOP); + } + }); + break; + case "marginBottom": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.BOTTOM, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.BOTTOM, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.BOTTOM); + } + }); + break; + case "marginStart": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.START, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.START, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.START); + } + }); + break; + case "marginEnd": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.END, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.END, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.END); + } + }); + break; + case "marginHorizontal": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.HORIZONTAL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.HORIZONTAL, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.HORIZONTAL); + } + }); + break; + case "marginVertical": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.VERTICAL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.VERTICAL, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.VERTICAL); + } + }); + break; + case "margin": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMargin(YogaEdge.ALL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMarginPercent(YogaEdge.ALL, v); + } + + @Override + public void setAuto() { + yogaNode.setMarginAuto(YogaEdge.ALL); + } + }); + break; + + + case "paddingLeft": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.LEFT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.LEFT, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingRight": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.RIGHT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.RIGHT, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingTop": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.TOP, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.TOP, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingBottom": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.BOTTOM, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.BOTTOM, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingStart": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.START, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.START, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingEnd": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.END, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.END, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingHorizontal": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.HORIZONTAL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.HORIZONTAL, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "paddingVertical": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.VERTICAL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.VERTICAL, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "padding": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPadding(YogaEdge.ALL, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPaddingPercent(YogaEdge.ALL, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "borderLeftWidth": + yogaNode.setBorder(YogaEdge.LEFT, value.asNumber().toFloat()); + break; + case "borderRightWidth": + yogaNode.setBorder(YogaEdge.RIGHT, value.asNumber().toFloat()); + break; + case "borderTopWidth": + yogaNode.setBorder(YogaEdge.TOP, value.asNumber().toFloat()); + break; + case "borderBottomWidth": + yogaNode.setBorder(YogaEdge.BOTTOM, value.asNumber().toFloat()); + break; + case "borderStartWidth": + yogaNode.setBorder(YogaEdge.START, value.asNumber().toFloat()); + break; + case "borderEndWidth": + yogaNode.setBorder(YogaEdge.END, value.asNumber().toFloat()); + break; + case "borderWidth": + yogaNode.setBorder(YogaEdge.ALL, value.asNumber().toFloat()); + break; + case "left": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.LEFT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.LEFT, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "right": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.RIGHT, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.RIGHT, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "top": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.TOP, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.TOP, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "bottom": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.BOTTOM, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.BOTTOM, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "start": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.START, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.START, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "end": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setPosition(YogaEdge.END, v); + } + + @Override + public void setPercent(float v) { + yogaNode.setPositionPercent(YogaEdge.END, v); + } + + @Override + public void setAuto() { + } + }); + break; + case "width": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setWidth(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setWidthPercent(v); + } + + @Override + public void setAuto() { + yogaNode.setWidthAuto(); + } + }); + break; + case "height": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setHeight(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setHeightPercent(v); + } + + @Override + public void setAuto() { + yogaNode.setHeightAuto(); + } + }); + break; + case "minWidth": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMinWidth(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMinHeightPercent(v); + } + + @Override + public void setAuto() { + } + }); + break; + case "minHeight": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMinHeight(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMinHeightPercent(v); + } + + @Override + public void setAuto() { + } + }); + break; + case "maxWidth": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMaxWidth(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMaxWidthPercent(v); + } + + @Override + public void setAuto() { + } + }); + break; + case "maxHeight": + setYogaValue(value, new YogaSetting() { + @Override + public void setPoint(float v) { + yogaNode.setMaxHeight(v); + } + + @Override + public void setPercent(float v) { + yogaNode.setMaxHeightPercent(v); + } + + @Override + public void setAuto() { + } + }); + break; + case "aspectRatio": + yogaNode.setAspectRatio(value.asNumber().toFloat()); + break; + default: + DoricLog.e("Cannot find flex config", name); + break; + } + } + + private interface YogaSetting { + void setPoint(float v); + + void setPercent(float v); + + void setAuto(); + } + + private void setYogaValue(JSValue value, YogaSetting setting) { + if (value.isNumber()) { + setting.setPoint(DoricUtils.dp2px(value.asNumber().toFloat())); + } else if (value.isObject()) { + JSValue jsType = value.asObject().getProperty("type"); + JSValue jsValue = value.asObject().getProperty("value"); + if (jsType.isNumber()) { + switch (jsType.asNumber().toInt()) { + case FLEX_VALUE_TYPE_POINT: + setting.setPoint(DoricUtils.dp2px(jsValue.asNumber().toFloat())); + break; + case FLEX_VALUE_TYPE_PERCENT: + setting.setPercent(jsValue.asNumber().toFloat()); + break; + default: + setting.setAuto(); + break; + } + } + } + } } diff --git a/doric-demo/src/FlexDemo.ts b/doric-demo/src/FlexDemo.ts index 6a6c6f8d..1e493c94 100644 --- a/doric-demo/src/FlexDemo.ts +++ b/doric-demo/src/FlexDemo.ts @@ -1,6 +1,6 @@ import { Group, Panel, text, gravity, Color, LayoutSpec, vlayout, hlayout, scroller, IVLayout, IHLayout, layoutConfig, stack, Gravity, flexlayout } from "doric"; -import { FlexDirection, Wrap, Justify, Align } from "doric/lib/src/util/flexbox"; +import { FlexDirection, Wrap, Justify, Align, FlexTypedValue } from "doric/lib/src/util/flexbox"; const colors = [ "#f0932b", @@ -61,15 +61,15 @@ class LayoutDemo extends Panel { box(4), ], { - layoutConfig: layoutConfig().most(), + layoutConfig: layoutConfig().fit(), backgroundColor: Color.GRAY, flexConfig: { - flexDirection: FlexDirection.ROW, - width: 200, - height: 200, - justifyContent: Justify.CENTER, + flexDirection: FlexDirection.COLUMN, + justifyContent: Justify.SPACE_EVENLY, alignContent: Align.CENTER, flexWrap: Wrap.WRAP, + width: FlexTypedValue.Auto, + height: FlexTypedValue.Auto, } } )