diff --git a/doric-android/doric/src/main/java/pub/doric/shader/DoricLayer.java b/doric-android/doric/src/main/java/pub/doric/shader/DoricLayer.java index ad9b52eb..d75de530 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/DoricLayer.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/DoricLayer.java @@ -21,22 +21,17 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Region; -import android.os.Build; -import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; /** * @Description: com.github.penfeizhou.doric.shader * @Author: pengfei.zhou * @CreateDate: 2019-07-31 */ -public class DoricLayer extends FrameLayout { +public class DoricLayer extends MaximumFrameLayout { private final Path mCornerPath = new Path(); private Paint mShadowPaint; private Paint mBorderPaint; @@ -47,19 +42,6 @@ public class DoricLayer extends FrameLayout { super(context); } - public DoricLayer(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public DoricLayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public DoricLayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -67,6 +49,16 @@ public class DoricLayer extends FrameLayout { @Override public void draw(Canvas canvas) { + mRect.left = 0; + mRect.right = getWidth(); + mRect.top = 0; + mRect.bottom = getHeight(); + if (mCornerRadii != null) { + canvas.save(); + mCornerPath.reset(); + mCornerPath.addRoundRect(mRect, mCornerRadii, Path.Direction.CW); + canvas.clipPath(mCornerPath); + } super.draw(canvas); } @@ -81,6 +73,9 @@ public class DoricLayer extends FrameLayout { mRect.right = getWidth(); mRect.top = 0; mRect.bottom = getHeight(); + if (canvas.getSaveCount() > 1) { + canvas.restore(); + } canvas.save(); if (mCornerRadii != null) { mCornerPath.reset(); diff --git a/doric-android/doric/src/main/java/pub/doric/shader/MaximumFrameLayout.java b/doric-android/doric/src/main/java/pub/doric/shader/MaximumFrameLayout.java new file mode 100644 index 00000000..dae4b6af --- /dev/null +++ b/doric-android/doric/src/main/java/pub/doric/shader/MaximumFrameLayout.java @@ -0,0 +1,158 @@ +/* + * Copyright [2019] [Doric.Pub] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package pub.doric.shader; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.FrameLayout; + +import java.util.ArrayList; + +/** + * @Description: MaximumFrameLayout + * @Author: pengfei.zhou + * @CreateDate: 2021/9/2 + */ +class MaximumFrameLayout extends FrameLayout { + int maxWidth = Integer.MAX_VALUE; + 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) { + rawOnMeasure(widthMeasureSpec, heightMeasureSpec); + int width = getMeasuredWidth(); + int height = getMeasuredHeight(); + if (width > maxWidth || height > maxHeight) { + width = Math.min(width, maxWidth); + height = Math.min(height, maxHeight); + widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); + rawOnMeasure(widthMeasureSpec, heightMeasureSpec); + } + } +} 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 8e8c33ad..0dab4b52 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 @@ -15,9 +15,6 @@ */ 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; @@ -28,8 +25,6 @@ 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,136 +32,6 @@ import java.util.ArrayList; */ @DoricPlugin(name = "Stack") 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) { - rawOnMeasure(widthMeasureSpec, heightMeasureSpec); - int width = getMeasuredWidth(); - int height = getMeasuredHeight(); - if (width > maxWidth || height > maxHeight) { - width = Math.min(width, maxWidth); - height = Math.min(height, maxHeight); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - rawOnMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - } - public StackNode(DoricContext doricContext) { super(doricContext); @@ -196,7 +61,7 @@ public class StackNode extends GroupNode { @Override protected FrameLayout build() { - return new MaximumFrameLayout(getContext()); + return new DoricLayer(getContext()); } @Override 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 30341c8c..c0ca4678 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 @@ -36,7 +36,6 @@ import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; -import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.appcompat.widget.DoricLinearLayoutCompat; @@ -543,6 +542,9 @@ public abstract class ViewNode extends DoricContextHolder { @NonNull private DoricLayer requireDoricLayer() { + if (mView instanceof DoricLayer) { + return (DoricLayer) mView; + } if (doricLayer == null) { doricLayer = new DoricLayer(getContext()); doricLayer.setLayoutParams(mLayoutParams); diff --git a/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java b/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java index 4048578b..d15f756d 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java @@ -15,12 +15,8 @@ */ package pub.doric.shader.list; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.view.View; import android.widget.FrameLayout; -import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSValue;