/**
* @Description: 类作用描述
* @Author: hukui
* @Date: 2020/9/7 17:20
*/
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.mylibrary.api.R;
/**
* 尝试一个自定义阴影View
*/
public class ShadeViewGroup extends ViewGroup {
private float deltaLength;
private float cornerRadius;
private Paint mShadowPaint;
private boolean drawShadow;
private Context mContext;
private int shadowColor;
private float shadowRadius;
private float dx;
private float dy;
public ShadeViewGroup(Context context) {
this(context, null);
}
public ShadeViewGroup(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ShadeViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initView(attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child = getChildAt(0);
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int childMeasureWidth = child.getMeasuredWidth();
int childMeasureHeight = child.getMeasuredHeight();
child.layout((measuredWidth - childMeasureWidth) / 2, (measuredHeight - childMeasureHeight) / 2, (measuredWidth + childMeasureWidth) / 2, (measuredHeight + childMeasureHeight) / 2);
}
/**
* 初始化信息变量
*/
private void initView(AttributeSet attrs) {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.ShadeViewGroup);
shadowColor = a.getColor(R.styleable.ShadeViewGroup_containerShadowColor, Color.WHITE);
shadowRadius = a.getDimension(R.styleable.ShadeViewGroup_containerShadowRadius, 0);
dx = a.getDimension(R.styleable.ShadeViewGroup_deltaX, 0);
dy = a.getDimension(R.styleable.ShadeViewGroup_deltaY, 0);
deltaLength = a.getDimension(R.styleable.ShadeViewGroup_containerDeltaLength, 0);
cornerRadius = a.getDimension(R.styleable.ShadeViewGroup_containerCornerRadius, 0);
drawShadow = a.getBoolean(R.styleable.ShadeViewGroup_enable, true);
a.recycle();
initShadowPaint();
}
public void setShadowColor(int shadowColor) {
this.shadowColor = shadowColor;
initShadowPaint();
invalidate();
}
private void initShadowPaint() {
mShadowPaint = new Paint();
mShadowPaint.setStyle(Paint.Style.FILL);
mShadowPaint.setAntiAlias(true);
mShadowPaint.setColor(shadowColor);
mShadowPaint.setShadowLayer(shadowRadius, dx, dy, shadowColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() != 1) {
throw new IllegalStateException("子View只能有一个");
}
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
View child = getChildAt(0);
LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
int childBottomMargin = (int) (Math.max(deltaLength, layoutParams.bottomMargin) + 1);
int childLeftMargin = (int) (Math.max(deltaLength, layoutParams.leftMargin) + 1);
int childRightMargin = (int) (Math.max(deltaLength, layoutParams.rightMargin) + 1);
int childTopMargin = (int) (Math.max(deltaLength, layoutParams.topMargin) + 1);
int widthMeasureSpecMode;
int widthMeasureSpecSize;
int heightMeasureSpecMode;
int heightMeasureSpecSize;
if (widthMode == MeasureSpec.UNSPECIFIED) {
widthMeasureSpecMode = MeasureSpec.UNSPECIFIED;
widthMeasureSpecSize = MeasureSpec.getSize(widthMeasureSpec);
} else {
if (layoutParams.width == LayoutParams.MATCH_PARENT) {
widthMeasureSpecMode = MeasureSpec.EXACTLY;
widthMeasureSpecSize = measuredWidth - childLeftMargin - childRightMargin;
} else if (LayoutParams.WRAP_CONTENT == layoutParams.width) {
widthMeasureSpecMode = MeasureSpec.AT_MOST;
widthMeasureSpecSize = measuredWidth - childLeftMargin - childRightMargin;
} else {
widthMeasureSpecMode = MeasureSpec.EXACTLY;
widthMeasureSpecSize = layoutParams.width;
}
}
if (heightMode == MeasureSpec.UNSPECIFIED) {
heightMeasureSpecMode = MeasureSpec.UNSPECIFIED;
heightMeasureSpecSize = MeasureSpec.getSize(heightMeasureSpec);
} else {
if (layoutParams.height == LayoutParams.MATCH_PARENT) {
heightMeasureSpecMode = MeasureSpec.EXACTLY;
heightMeasureSpecSize = measuredHeight - childBottomMargin - childTopMargin;
} else if (LayoutParams.WRAP_CONTENT == layoutParams.height) {
heightMeasureSpecMode = MeasureSpec.AT_MOST;
heightMeasureSpecSize = measuredHeight - childBottomMargin - childTopMargin;
} else {
heightMeasureSpecMode = MeasureSpec.EXACTLY;
heightMeasureSpecSize = layoutParams.height;
}
}
measureChild(child, MeasureSpec.makeMeasureSpec(widthMeasureSpecSize, widthMeasureSpecMode), MeasureSpec.makeMeasureSpec(heightMeasureSpecSize, heightMeasureSpecMode));
int parentWidthMeasureSpec = MeasureSpec.getMode(widthMeasureSpec);
int parentHeightMeasureSpec = MeasureSpec.getMode(heightMeasureSpec);
int height = measuredHeight;
int width = measuredWidth;
int childHeight = child.getMeasuredHeight();
int childWidth = child.getMeasuredWidth();
if (parentHeightMeasureSpec == MeasureSpec.AT_MOST) {
height = childHeight + childTopMargin + childBottomMargin;
}
if (parentWidthMeasureSpec == MeasureSpec.AT_MOST) {
width = childWidth + childRightMargin + childLeftMargin;
}
if (width < childWidth + 2 * deltaLength) {
width = (int) (childWidth + 2 * deltaLength);
}
if (height < childHeight + 2 * deltaLength) {
height = (int) (childHeight + 2 * deltaLength);
}
if (height != measuredHeight || width != measuredWidth) {
setMeasuredDimension(width, height);
}
}
static class LayoutParams extends MarginLayoutParams {
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void dispatchDraw(Canvas canvas) {
if (drawShadow) {
if (getLayerType() != LAYER_TYPE_SOFTWARE) {
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
View child = getChildAt(0);
int left = child.getLeft();
int top = child.getTop();
int right = child.getRight();
int bottom = child.getBottom();
RectF rectF = new RectF(left, top, right, bottom);
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, mShadowPaint);
}
super.dispatchDraw(canvas);
}
}
<declare-styleable name="ShadeViewGroup">
<attr name="containerShadowColor" format="color" />
<attr name="containerShadowRadius" format="dimension" />
<attr name="containerDeltaLength" format="dimension" />
<attr name="containerCornerRadius" format="dimension" />
<attr name="deltaX" format="dimension" />
<attr name="deltaY" format="dimension" />
<attr name="enable" format="boolean" />
</declare-styleable>
简单用法
<com.mylibrary.api.widget.ShadeViewGroup
android:id="@+id/shopCar_EditLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="-6dp"
android:layout_marginEnd="-6dp"
android:layout_marginBottom="-6dp"
android:visibility="gone"
app:containerCornerRadius="@dimen/radius2"
app:containerDeltaLength="@dimen/shardRadius"
app:containerShadowColor="@color/shadowColor"
app:containerShadowRadius="@dimen/shardRadius"></com.mylibrary.api.widget.ShadeViewGroup>