From 05927b33d5140493f08e476d3cdf21b020001f42 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Thu, 23 Apr 2020 19:54:25 +0800 Subject: [PATCH] fix when parent is fit ,child is most,resolve this situation --- .../main/java/pub/doric/shader/StackNode.java | 117 +++++++++++++++++- doric-demo/src/LayoutTestDemo.ts | 73 +++++++++++ doric-iOS/Pod/Classes/Shader/DoricLayouts.m | 27 ++++ 3 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 doric-demo/src/LayoutTestDemo.ts diff --git a/doric-android/doric/src/main/java/pub/doric/shader/StackNode.java b/doric-android/doric/src/main/java/pub/doric/shader/StackNode.java index 659bd136..8e8c33ad 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/StackNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/StackNode.java @@ -16,9 +16,10 @@ package pub.doric.shader; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.LinearLayout; import pub.doric.DoricContext; import pub.doric.extension.bridge.DoricPlugin; @@ -27,6 +28,8 @@ import pub.doric.utils.DoricUtils; import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSValue; +import java.util.ArrayList; + /** * @Description: com.github.penfeizhou.doric.widget * @Author: pengfei.zhou @@ -37,15 +40,121 @@ public class StackNode extends GroupNode { private static class MaximumFrameLayout extends FrameLayout { private int maxWidth = Integer.MAX_VALUE; private int maxHeight = Integer.MAX_VALUE; - + private final ArrayList mMatchParentChildren = new ArrayList<>(1); public MaximumFrameLayout(Context context) { super(context); } + int getPaddingLeftWithForeground() { + return getPaddingLeft(); + } + + int getPaddingRightWithForeground() { + return getPaddingRight(); + } + + private int getPaddingTopWithForeground() { + return getPaddingTop(); + } + + private int getPaddingBottomWithForeground() { + return getPaddingBottom(); + } + + private void rawOnMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + mMatchParentChildren.clear(); + + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (getMeasureAllChildren() || child.getVisibility() != GONE) { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + maxWidth = Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + maxHeight = Math.max(maxHeight, + child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + if (measureMatchParentChildren) { + if (lp.width == LayoutParams.MATCH_PARENT || + lp.height == LayoutParams.MATCH_PARENT) { + mMatchParentChildren.add(child); + } + } + } + } + + // Account for padding too + maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground(); + maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground(); + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Check against our foreground's minimum height and width + final Drawable drawable = getForeground(); + if (drawable != null) { + maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + } + + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + + count = mMatchParentChildren.size(); + if (count > 0) { + for (int i = 0; i < count; i++) { + final View child = mMatchParentChildren.get(i); + final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); + + final int childWidthMeasureSpec; + if (lp.width == LayoutParams.MATCH_PARENT) { + final int width = Math.max(0, getMeasuredWidth() + - getPaddingLeftWithForeground() - getPaddingRightWithForeground() + - lp.leftMargin - lp.rightMargin); + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + width, MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeftWithForeground() + getPaddingRightWithForeground() + + lp.leftMargin + lp.rightMargin, + lp.width); + } + + final int childHeightMeasureSpec; + if (lp.height == LayoutParams.MATCH_PARENT) { + final int height = Math.max(0, getMeasuredHeight() + - getPaddingTopWithForeground() - getPaddingBottomWithForeground() + - lp.topMargin - lp.bottomMargin); + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + height, MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTopWithForeground() + getPaddingBottomWithForeground() + + lp.topMargin + lp.bottomMargin, + lp.height); + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + rawOnMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); if (width > maxWidth || height > maxHeight) { @@ -53,7 +162,7 @@ public class StackNode extends GroupNode { height = Math.min(height, maxHeight); widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + rawOnMeasure(widthMeasureSpec, heightMeasureSpec); } } } diff --git a/doric-demo/src/LayoutTestDemo.ts b/doric-demo/src/LayoutTestDemo.ts new file mode 100644 index 00000000..2283453e --- /dev/null +++ b/doric-demo/src/LayoutTestDemo.ts @@ -0,0 +1,73 @@ +import { Panel, Group, vlayout, LayoutSpec, text, Color, gravity, stack, layoutConfig } from "doric"; + +@Entry +class LayoutTest extends Panel { + build(root: Group) { + vlayout( + [ + text({ + text: "Fit -> Most", + layoutConfig: { + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, + }, + textSize: 30, + textColor: Color.parse("#535c68"), + backgroundColor: Color.parse("#dff9fb"), + textAlignment: gravity().center(), + height: 50, + }), + stack( + [ + stack( + [], + { + layoutConfig: layoutConfig().most(), + backgroundColor: Color.BLUE + } + ), + text({ + text: "This is a stack content", + textSize: 20, + textColor: Color.WHITE, + }), + ], + { + layoutConfig: { + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, + }, + backgroundColor: Color.RED + }), + vlayout( + [ + stack( + [], + { + layoutConfig: layoutConfig().most(), + backgroundColor: Color.BLUE + } + ), + text({ + text: "This is a stack content", + textSize: 20, + textColor: Color.WHITE, + }), + ], + { + layoutConfig: { + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, + }, + backgroundColor: Color.RED + }) + ], + { + layoutConfig: { + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.FIT, + }, + space: 20, + }).in(root) + } +} \ No newline at end of file diff --git a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m index 0224aa7c..53b926ba 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m +++ b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m @@ -156,6 +156,12 @@ - (void)measureContent:(CGSize)targetSize { break; } } + if (self.view.superview.doricLayout.widthSpec == DoricLayoutFit && self.widthSpec == DoricLayoutMost) { + self.measuredWidth = 0; + } + if (self.view.superview.doricLayout.heightSpec == DoricLayoutFit && self.heightSpec == DoricLayoutMost) { + self.measuredHeight = 0; + } } - (void)layout { @@ -373,6 +379,12 @@ - (void)layoutStack { if (layout.disabled) { continue; } + if (self.widthSpec == DoricLayoutFit && layout.widthSpec == DoricLayoutMost) { + layout.measuredWidth = self.measuredWidth - layout.marginLeft - layout.marginRight; + } + if (self.heightSpec == DoricLayoutFit && layout.heightSpec == DoricLayoutMost) { + layout.measuredHeight = self.measuredHeight - layout.marginTop - layout.marginBottom; + } [layout layout]; DoricGravity gravity = layout.alignment; if ((gravity & DoricGravityLeft) == DoricGravityLeft) { @@ -434,6 +446,12 @@ - (void)layoutVLayout { if (layout.disabled) { continue; } + if (self.widthSpec == DoricLayoutFit && layout.widthSpec == DoricLayoutMost) { + layout.measuredWidth = self.measuredWidth - layout.marginLeft - layout.marginRight; + } + if (self.heightSpec == DoricLayoutFit && layout.heightSpec == DoricLayoutMost) { + layout.measuredHeight = self.measuredHeight - yStart - layout.marginTop - layout.marginBottom; + } [layout layout]; DoricGravity gravity = layout.alignment | self.gravity; if ((gravity & DoricGravityLeft) == DoricGravityLeft) { @@ -473,6 +491,15 @@ - (void)layoutHLayout { if (layout.disabled) { continue; } + + if (self.widthSpec == DoricLayoutFit && layout.widthSpec == DoricLayoutMost) { + layout.measuredWidth = self.measuredWidth - xStart - layout.marginLeft - layout.marginRight; + } + + if (self.heightSpec == DoricLayoutFit && layout.heightSpec == DoricLayoutMost) { + layout.measuredHeight = self.measuredHeight - layout.marginTop - layout.marginBottom; + } + [layout layout]; DoricGravity gravity = layout.alignment | self.gravity;