Android阴影布局的实现

1.上代码。

//第一部分

package com.mobile.common_library.custom_view;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.mobile.common_library.R;
import com.mobile.common_library.manager.GlideRoundManager;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

public class ShadowLinearLayout extends LinearLayout {

    private Drawable clickAbleFalseDrawable;
    private int clickAbleFalseColor = -101;

    private Drawable layoutBackground;
    private Drawable layoutBackground_true;
    private View firstView;

    private int mBackGroundColor;
    private int mBackGroundColor_true = -101;
    private int mShadowColor;
    private float mShadowLimit;
    private float mCornerRadius;
    private float mDx;
    private float mDy;
    private boolean leftShow;
    private boolean rightShow;
    private boolean topShow;
    private boolean bottomShow;
    private Paint shadowPaint;
    private Paint paint;

    private int leftPadding;
    private int topPadding;
    private int rightPadding;
    private int bottomPadding;
    //阴影布局子空间区域
    private RectF rectf = new RectF();

    //ShadowLinearLayout的样式,是只需要pressed还是selected。默认是pressed.
    private int selectorType = 1;
    private boolean isShowShadow = true;
    private boolean isSym;

    //增加各个圆角的属性
    private float mCornerRadius_leftTop;
    private float mCornerRadius_rightTop;
    private float mCornerRadius_leftBottom;
    private float mCornerRadius_rightBottom;

    //边框画笔
    private Paint paint_stroke;
    private float stroke_with;
    private int stroke_color;
    private int stroke_color_true;

    private boolean isClickable;


    //关于控件填充渐变色
    private int startColor;
    private int centerColor;
    private int endColor;
    private int angle;


    //在普遍情况,在点击或选中按钮时,很可能伴随着textView的字体颜色变化
    private int mTextViewResId = -1;
    private TextView mTextView;
    private int textColor;
    private int textColor_true;
    private String text;
    private String text_true;


    public ShadowLinearLayout(Context context) {
        this(context, null);
    }

    public ShadowLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public ShadowLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }


    public void setClickable(boolean clickable) {
        super.setClickable(clickable);
        this.isClickable = clickable;
        changeSwitchClickable();
        if (isClickable) {
            super.setOnClickListener(onClickListener);
        }

        if (paint != null) {
            if (startColor != -101 && endColor != -101) {
                gradient(paint);
            }
        }
    }


    //解决xml设置clickable = false时。代码设置true时,点击事件无效的bug
    private OnClickListener onClickListener;

    @Override
    public void setOnClickListener(@Nullable OnClickListener l) {
        this.onClickListener = l;
        if (isClickable) {
            super.setOnClickListener(l);
        }
    }

    public void changeSwitchClickable() {
        //不可点击的状态只在press mode的模式下生效
        if (selectorType == 1 && firstView != null) {

            //press mode
            if (!isClickable) {
                //不可点击的状态。
                if (clickAbleFalseColor != -101) {
                    //说明设置了颜色
                    if (layoutBackground != null) {
                        //说明此时是设置了图片的模式
                        firstView.getBackground().setAlpha(0);
                    }
                    paint.setColor(clickAbleFalseColor);
                    postInvalidate();


                } else if (clickAbleFalseDrawable != null) {
                    //说明设置了背景图
                    setmBackGround(clickAbleFalseDrawable);
                    paint.setColor(Color.parseColor("#00000000"));
                    postInvalidate();
                }
            } else {
                //可点击的状态
                if (layoutBackground != null) {
                    setmBackGround(layoutBackground);
                } else {
                    if (firstView.getBackground() != null) {
                        firstView.getBackground().setAlpha(0);
                    }
                }
                paint.setColor(mBackGroundColor);
                postInvalidate();
            }
        }
    }

    //增加selector样式
    @Override
    public void setSelected(boolean selected) {
        super.setSelected(selected);
        if (getWidth() != 0) {
            if (selectorType == 2) {
                if (selected) {
                    if (mBackGroundColor_true != -101) {
                        paint.setColor(mBackGroundColor_true);
                    }

                    paint.setShader(null);
                    if (stroke_color_true != -101) {
                        paint_stroke.setColor(stroke_color_true);
                    }
                    if (layoutBackground_true != null) {
                        setmBackGround(layoutBackground_true);
                    }

                    if (mTextView != null) {
                        mTextView.setTextColor(textColor_true);
                        if (!TextUtils.isEmpty(text_true)) {
                            mTextView.setText(text_true);
                        }
                    }

                } else {
                    paint.setColor(mBackGroundColor);
                    if (startColor != -101) {
                        gradient(paint);
                    }

                    if (stroke_color != -101) {
                        paint_stroke.setColor(stroke_color);
                    }

                    if (layoutBackground != null) {
                        setmBackGround(layoutBackground);
                    }

                    if (mTextView != null) {
                        mTextView.setTextColor(textColor);
                        if (!TextUtils.isEmpty(text)) {
                            mTextView.setText(text);
                        }
                    }

                }
                postInvalidate();
            }
        } else {
            addOnLayoutChangeListener(new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    removeOnLayoutChangeListener(this);
                    setSelected(isSelected());
                }
            });
        }
    }


    //是否隐藏阴影
    public void setShadowHidden(boolean isShowShadow) {
        this.isShowShadow = !isShowShadow;
        if (getWidth() != 0 && getHeight() != 0) {
            setBackgroundCompat(getWidth(), getHeight());
        }
    }

    //设置x轴偏移量
    public void setShadowOffsetX(float mDx) {
        if (isShowShadow) {
            if (Math.abs(mDx) > mShadowLimit) {
                if (mDx > 0) {
                    this.mDx = mShadowLimit;
                } else {
                    this.mDx = -mShadowLimit;
                }
            } else {
                this.mDx = mDx;
            }
            setPadding();
        }
    }

    //动态设置y轴偏移量
    public void setShadowOffsetY(float mDy) {
        if (isShowShadow) {
            if (Math.abs(mDy) > mShadowLimit) {
                if (mDy > 0) {
                    this.mDy = mShadowLimit;
                } else {
                    this.mDy = -mShadowLimit;
                }
            } else {
                this.mDy = mDy;
            }
            setPadding();
        }
    }


    public float getCornerRadius() {
        return mCornerRadius;
    }

    //动态设置 圆角属性
    public void setCornerRadius(int mCornerRadius) {
        this.mCornerRadius = mCornerRadius;
        if (getWidth() != 0 && getHeight() != 0) {
            setBackgroundCompat(getWidth(), getHeight());
        }
    }

    public float getShadowLimit() {
        return mShadowLimit;
    }

    //动态设置阴影扩散区域
    public void setShadowLimit(int mShadowLimit) {
        if (isShowShadow) {
            int dip5 = (int) getContext().getResources().getDimension(R.dimen.dp_5);
            if (mShadowLimit >= dip5) {
                this.mShadowLimit = mShadowLimit;
            } else {
                this.mShadowLimit = dip5;
            }
            setPadding();
        }
    }

    //动态设置阴影颜色值
    public void setShadowColor(int mShadowColor) {
        this.mShadowColor = mShadowColor;
        if (getWidth() != 0 && getHeight() != 0) {
            setBackgroundCompat(getWidth(), getHeight());
        }
    }


    public void setSpecialCorner(int leftTop, int rightTop, int leftBottom, int rightBottom) {
        mCornerRadius_leftTop = leftTop;
        mCornerRadius_rightTop = rightTop;
        mCornerRadius_leftBottom = leftBottom;
        mCornerRadius_rightBottom = rightBottom;
        if (getWidth() != 0 && getHeight() != 0) {
            setBackgroundCompat(getWidth(), getHeight());
        }
    }


    //是否隐藏阴影的上边部分
    public void setShadowHiddenTop(boolean topShow) {
        this.topShow = !topShow;
        setPadding();
    }

    public void setShadowHiddenBottom(boolean bottomShow) {
        this.bottomShow = !bottomShow;
        setPadding();
    }


    public void setShadowHiddenRight(boolean rightShow) {
        this.rightShow = !rightShow;
        setPadding();
    }


    public void setShadowHiddenLeft(boolean leftShow) {
        this.leftShow = !leftShow;
        setPadding();
    }


    public void setLayoutBackground(int color) {
        if (layoutBackground_true != null) {
            throw new UnsupportedOperationException("使用了ShadowLinearLayout_hl_layoutBackground_true属性,要与ShadowLinearLayout_hl_layoutBackground属性统一为颜色");
        }
        mBackGroundColor = color;
        if (selectorType == 2) {
            //select模式
            if (!this.isSelected()) {
                paint.setColor(mBackGroundColor);
            }
        } else {
            paint.setColor(mBackGroundColor);
        }
        postInvalidate();
    }


    public void setLayoutBackgroundTrue(int color) {
        if (layoutBackground != null) {
            throw new UnsupportedOperationException("使用了ShadowLinearLayout_hl_layoutBackground属性,要与ShadowLinearLayout_hl_layoutBackground_true属性统一为颜色");
        }
        mBackGroundColor_true = color;
        if (selectorType == 2) {
            //select模式
            if (this.isSelected()) {
                paint.setColor(mBackGroundColor_true);
            }
        }
        postInvalidate();
    }


    public void setStrokeColor(int color) {
        stroke_color = color;
        if (selectorType == 2) {
            //select模式
            if (!this.isSelected()) {
                paint_stroke.setColor(stroke_color);
            }
        } else {
            paint_stroke.setColor(stroke_color);
        }
        postInvalidate();
    }


    public void setStrokeColorTrue(int color) {

        stroke_color_true = color;
        if (selectorType == 2) {
            //select模式
            if (this.isSelected()) {
                paint_stroke.setColor(stroke_color_true);
            }
        }
        postInvalidate();
    }

    public void setStrokeWidth(int stokeWidth) {
        this.stroke_with = stokeWidth;
        if (stroke_with > dip2px(7)) {
            stroke_with = dip2px(5);
        }
        paint_stroke.setStrokeWidth(stroke_with);
        postInvalidate();
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (mTextViewResId != -1) {
            mTextView = findViewById(mTextViewResId);
            if (mTextView == null) {
                throw new NullPointerException("ShadowLinearLayout找不到hl_bindTextView,请确保绑定的资源id在ShadowLinearLayout内");
            } else {
                if (textColor == -101) {
                    textColor = mTextView.getCurrentTextColor();
                }


                if (textColor_true == -101) {
                    textColor_true = mTextView.getCurrentTextColor();
                }

                mTextView.setTextColor(textColor);
                if (!TextUtils.isEmpty(text)) {
                    mTextView.setText(text);
                }
            }
        }

        firstView = getChildAt(0);
        if (firstView == null) {
            firstView = ShadowLinearLayout.this;
            //当子View都没有的时候。默认不使用阴影
            isShowShadow = false;
        }

        if (firstView != null) {

            //selector样式不受clickable的影响

            if (selectorType == 2) {
                //if (this.isSelected()) {
                //这个方法内已经判断了是否为空
                //  setmBackGround(layoutBackground_true);
                //} else {
                //  setmBackGround(layoutBackground);
                //  }
            } else {
                if (isClickable) {
                    setmBackGround(layoutBackground);
                } else {
                    setmBackGround(clickAbleFalseDrawable);
                    if (clickAbleFalseColor != -101) {
                        paint.setColor(clickAbleFalseColor);
                    }
                }
            }

        }

    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (w > 0 && h > 0) {
            setBackgroundCompat(w, h);
            if (startColor != -101) {
                gradient(paint);
            }
        }
    }

    private void initView(Context context, AttributeSet attrs) {
        initAttributes(attrs);
        shadowPaint = new Paint();
        shadowPaint.setAntiAlias(true);
        shadowPaint.setStyle(Paint.Style.FILL);


        paint_stroke = new Paint();
        paint_stroke.setAntiAlias(true);
        paint_stroke.setStyle(Paint.Style.STROKE);
        paint_stroke.setStrokeWidth(stroke_with);
        if (stroke_color != -101) {
            paint_stroke.setColor(stroke_color);
        }


        //矩形画笔
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL);
        //打个标记
        paint.setColor(mBackGroundColor);

        setPadding();


    }

    //将画笔附上 渐变色
    public void gradient(Paint paint) {
        if (!isClickable) {
            paint.setShader(null);
            return;
        }

        //左上 x,y   leftPadding, topPadding,
        //右下 x,y   getWidth() - rightPadding, getHeight() - bottomPadding
        int[] colors;
        if (centerColor == -101) {
            colors = new int[]{startColor, endColor};
        } else {
            colors = new int[]{startColor, centerColor, endColor};
        }

        if (angle < 0) {
            int trueAngle = angle % 360;
            angle = trueAngle + 360;
        }

        //当设置的角度大于0的时候
        //这个要算出每隔45度
        int trueAngle = angle % 360;
        int angleFlag = trueAngle / 45;
        LinearGradient linearGradient;
        switch (angleFlag) {
            case 0://0°
                linearGradient = new LinearGradient(leftPadding, topPadding, getWidth() - rightPadding, topPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 1://45°
                linearGradient = new LinearGradient(leftPadding, getHeight() - bottomPadding, getWidth() - rightPadding, topPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 2://90°
                int x_ = (getWidth() - rightPadding - leftPadding) / 2 + leftPadding;
                linearGradient = new LinearGradient(x_, getHeight() - bottomPadding, x_, topPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 3://135°
                linearGradient = new LinearGradient(getWidth() - rightPadding, getHeight() - bottomPadding, leftPadding, topPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;
            case 4://180°
                linearGradient = new LinearGradient(getWidth() - rightPadding, topPadding, leftPadding, topPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 5://225°
                linearGradient = new LinearGradient(getWidth() - rightPadding, topPadding, leftPadding, getHeight() - bottomPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 6://270°
                int x = (getWidth() - rightPadding - leftPadding) / 2 + leftPadding;
                linearGradient = new LinearGradient(x, topPadding, x, getHeight() - bottomPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

            case 7://315°
                linearGradient = new LinearGradient(leftPadding, topPadding, getWidth() - rightPadding, getHeight() - bottomPadding, colors, null, Shader.TileMode.CLAMP);
                paint.setShader(linearGradient);
                break;

        }


    }


    public int dip2px(float dipValue) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    public void setPadding() {
        if (isShowShadow && mShadowLimit > 0) {
            //控件区域是否对称,默认是对称。不对称的话,那么控件区域随着阴影区域走
            if (isSym) {
                int xPadding = (int) (mShadowLimit + Math.abs(mDx));
                int yPadding = (int) (mShadowLimit + Math.abs(mDy));

                if (leftShow) {
                    leftPadding = xPadding;
                } else {
                    leftPadding = 0;
                }

                if (topShow) {
                    topPadding = yPadding;
                } else {
                    topPadding = 0;
                }


                if (rightShow) {
                    rightPadding = xPadding;
                } else {
                    rightPadding = 0;
                }

                if (bottomShow) {
                    bottomPadding = yPadding;
                } else {
                    bottomPadding = 0;
                }
            } else {
                if (Math.abs(mDy) > mShadowLimit) {
                    if (mDy > 0) {
                        mDy = mShadowLimit;
                    } else {
                        mDy = 0 - mShadowLimit;
                    }
                }


                if (Math.abs(mDx) > mShadowLimit) {
                    if (mDx > 0) {
                        mDx = mShadowLimit;
                    } else {
                        mDx = 0 - mShadowLimit;
                    }
                }

                if (topShow) {
                    topPadding = (int) (mShadowLimit - mDy);
                } else {
                    topPadding = 0;
                }

                if (bottomShow) {
                    bottomPadding = (int) (mShadowLimit + mDy);
                } else {
                    bottomPadding = 0;
                }


                if (rightShow) {
                    rightPadding = (int) (mShadowLimit - mDx);
                } else {
                    rightPadding = 0;
                }


                if (leftShow) {
                    leftPadding = (int) (mShadowLimit + mDx);
                } else {
                    leftPadding = 0;
                }
            }
            setPadding(leftPadding, topPadding, rightPadding, bottomPadding);

//            setPadding(dip2px(leftPadding), dip2px(topPadding),
//                    dip2px(rightPadding), dip2px(bottomPadding));
        }
    }

    @SuppressWarnings("deprecation")
    private void setBackgroundCompat(int w, int h) {
        if (isShowShadow) {
            //判断传入的颜色值是否有透明度
            isAddAlpha(mShadowColor);
            Bitmap bitmap = createShadowBitmap(w, h, mCornerRadius, mShadowLimit, mDx, mDy, mShadowColor, Color.TRANSPARENT);
            BitmapDrawable drawable = new BitmapDrawable(bitmap);
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                setBackgroundDrawable(drawable);
            } else {
                setBackground(drawable);
            }
        } else {
            if (getChildAt(0) == null) {
                if (layoutBackground != null) {
                    firstView = ShadowLinearLayout.this;
                    if (isClickable) {
                        setmBackGround(layoutBackground);
                    } else {
                        changeSwitchClickable();
                    }
                } else {
                    //解决不执行onDraw方法的bug就是给其设置一个透明色
                    this.setBackgroundColor(Color.parseColor("#00000000"));
                }
            } else {
                this.setBackgroundColor(Color.parseColor("#00000000"));
            }


        }

    }


    private void initAttributes(AttributeSet attrs) {
        TypedArray attr = getContext().obtainStyledAttributes(attrs, R.styleable.ShadowLayout);
        if (attr == null) {
            return;
        }

        try {
            //默认是显示
            isShowShadow = !attr.getBoolean(R.styleable.ShadowLayout_hl_shadowHidden, false);
            leftShow = !attr.getBoolean(R.styleable.ShadowLayout_hl_shadowHiddenLeft, false);
            rightShow = !attr.getBoolean(R.styleable.ShadowLayout_hl_shadowHiddenRight, false);
            bottomShow = !attr.getBoolean(R.styleable.ShadowLayout_hl_shadowHiddenBottom, false);
            topShow = !attr.getBoolean(R.styleable.ShadowLayout_hl_shadowHiddenTop, false);
            mCornerRadius = attr.getDimension(R.styleable.ShadowLayout_hl_cornerRadius, getResources().getDimension(R.dimen.dp_0));
            mCornerRadius_leftTop = attr.getDimension(R.styleable.ShadowLayout_hl_cornerRadius_leftTop, -1);
            mCornerRadius_leftBottom = attr.getDimension(R.styleable.ShadowLayout_hl_cornerRadius_leftBottom, -1);
            mCornerRadius_rightTop = attr.getDimension(R.styleable.ShadowLayout_hl_cornerRadius_rightTop, -1);
            mCornerRadius_rightBottom = attr.getDimension(R.styleable.ShadowLayout_hl_cornerRadius_rightBottom, -1);

            //默认扩散区域宽度
            mShadowLimit = attr.getDimension(R.styleable.ShadowLayout_hl_shadowLimit, 0);
            if (mShadowLimit == 0) {
                //如果阴影没有设置阴影扩散区域,那么默认隐藏阴影
                isShowShadow = false;
            } else {
                int dip5 = (int) getContext().getResources().getDimension(R.dimen.dp_5);
                if (mShadowLimit < dip5) {
                    mShadowLimit = dip5;
                }
            }

            //x轴偏移量
            mDx = attr.getDimension(R.styleable.ShadowLayout_hl_shadowOffsetX, 0);
            //y轴偏移量
            mDy = attr.getDimension(R.styleable.ShadowLayout_hl_shadowOffsetY, 0);
            mShadowColor = attr.getColor(R.styleable.ShadowLayout_hl_shadowColor, getResources().getColor(R.color.default_shadow_color));

            selectorType = attr.getInt(R.styleable.ShadowLayout_hl_shapeMode, 1);
            isSym = attr.getBoolean(R.styleable.ShadowLayout_hl_shadowSymmetry, true);

            //背景颜色的点击(默认颜色为白色)
            mBackGroundColor = getResources().getColor(R.color.default_shadowback_color);

            Drawable background = attr.getDrawable(R.styleable.ShadowLayout_hl_layoutBackground);
            if (background != null) {
                if (background instanceof ColorDrawable) {
                    ColorDrawable colorDrawable = (ColorDrawable) background;
                    mBackGroundColor = colorDrawable.getColor();

                } else {
                    layoutBackground = background;
                }
            }

            Drawable trueBackground = attr.getDrawable(R.styleable.ShadowLayout_hl_layoutBackground_true);
            if (trueBackground != null) {
                if (trueBackground instanceof ColorDrawable) {
                    ColorDrawable colorDrawableTrue = (ColorDrawable) trueBackground;
                    mBackGroundColor_true = colorDrawableTrue.getColor();

                } else {
                    layoutBackground_true = trueBackground;
                }
            }

            if (mBackGroundColor_true != -101 && layoutBackground != null) {
                throw new UnsupportedOperationException("使用了ShadowLayout_hl_layoutBackground_true属性,必须先设置ShadowLayout_hl_layoutBackground属性。且设置颜色时,必须保持都为颜色");
            }

            if (layoutBackground == null && layoutBackground_true != null) {
                throw new UnsupportedOperationException("使用了ShadowLayout_hl_layoutBackground_true属性,必须先设置ShadowLayout_hl_layoutBackground属性。且设置图片时,必须保持都为图片");
            }

            //边框颜色的点击
            stroke_color = attr.getColor(R.styleable.ShadowLayout_hl_strokeColor, -101);
            stroke_color_true = attr.getColor(R.styleable.ShadowLayout_hl_strokeColor_true, -101);

            if (stroke_color == -101 && stroke_color_true != -101) {
                throw new UnsupportedOperationException("使用了ShadowLayout_hl_strokeColor_true属性,必须先设置ShadowLayout_hl_strokeColor属性");
            }

            stroke_with = attr.getDimension(R.styleable.ShadowLayout_hl_strokeWith, dip2px(1));
            //规定边框长度最大不错过7dp
            if (stroke_with > dip2px(7)) {
                stroke_with = dip2px(5);
            }


            Drawable clickAbleFalseBackground = attr.getDrawable(R.styleable.ShadowLayout_hl_layoutBackground_clickFalse);
            if (clickAbleFalseBackground != null) {
                if (clickAbleFalseBackground instanceof ColorDrawable) {
                    ColorDrawable colorDrawableClickableFalse = (ColorDrawable) clickAbleFalseBackground;
                    clickAbleFalseColor = colorDrawableClickableFalse.getColor();
                } else {
                    clickAbleFalseDrawable = clickAbleFalseBackground;
                }
            }


            startColor = attr.getColor(R.styleable.ShadowLayout_hl_startColor, -101);
            centerColor = attr.getColor(R.styleable.ShadowLayout_hl_centerColor, -101);
            endColor = attr.getColor(R.styleable.ShadowLayout_hl_endColor, -101);
            if (startColor != -101) {
                //说明设置了渐变色的起始色
                if (endColor == -101) {
                    throw new UnsupportedOperationException("使用了ShadowLayout_hl_startColor渐变起始色,必须搭配终止色ShadowLayout_hl_endColor");
                }
            }


            angle = attr.getInt(R.styleable.ShadowLayout_hl_angle, 0);
            if (angle % 45 != 0) {
                throw new IllegalArgumentException("Linear gradient requires 'angle' attribute to be a multiple of 45");
            }


            if (selectorType == 3) {
                //如果是ripple的话
                if (mBackGroundColor == -101 || mBackGroundColor_true == -101) {
                    throw new NullPointerException("使用了ShadowLayout的水波纹,必须设置使用了ShadowLayout_hl_layoutBackground和使用了ShadowLayout_hl_layoutBackground_true属性,且为颜色值");
                }

                //如果是设置了图片的话,那么也不支持水波纹
                if (layoutBackground != null) {
                    selectorType = 1;
                }
            }


            mTextViewResId = attr.getResourceId(R.styleable.ShadowLayout_hl_bindTextView, -1);
            textColor = attr.getColor(R.styleable.ShadowLayout_hl_textColor, -101);
            textColor_true = attr.getColor(R.styleable.ShadowLayout_hl_textColor_true, -101);
            text = attr.getString(R.styleable.ShadowLayout_hl_text);
            text_true = attr.getString(R.styleable.ShadowLayout_hl_text_true);

            isClickable = attr.getBoolean(R.styleable.ShadowLayout_clickable, true);
            setClickable(isClickable);


        } finally {
            attr.recycle();
        }
    }


    private Bitmap createShadowBitmap(int shadowWidth, int shadowHeight, float cornerRadius, float shadowRadius,
                                      float dx, float dy, int shadowColor, int fillColor) {
        //优化阴影bitmap大小,将尺寸缩小至原来的1/4。
        dx = dx / 4;
        dy = dy / 4;
        shadowWidth = shadowWidth / 4 == 0 ? 1 : shadowWidth / 4;
        shadowHeight = shadowHeight / 4 == 0 ? 1 : shadowHeight / 4;
        cornerRadius = cornerRadius / 4;
        shadowRadius = shadowRadius / 4;

        Bitmap output = Bitmap.createBitmap(shadowWidth, shadowHeight, Bitmap.Config.ARGB_4444);
        Canvas canvas = new Canvas(output);

        //这里缩小limit的是因为,setShadowLayer后会将bitmap扩散到shadowWidth,shadowHeight
        //同时也要根据某边的隐藏情况去改变

        float rect_left = 0;
        float rect_right = 0;
        float rect_top = 0;
        float rect_bottom = 0;
        if (leftShow) {
            rect_left = shadowRadius;
        } else {
//            rect_left = 0;
            float maxLeftTop = Math.max(cornerRadius, mCornerRadius_leftTop);
            float maxLeftBottom = Math.max(cornerRadius, mCornerRadius_leftBottom);
            float maxLeft = Math.max(maxLeftTop, maxLeftBottom);
            rect_left = maxLeft;
        }

        if (topShow) {
            rect_top = shadowRadius;
        } else {
//            rect_top = 0;
            float maxLeftTop = Math.max(cornerRadius, mCornerRadius_leftTop);
            float maxRightTop = Math.max(cornerRadius, mCornerRadius_rightTop);
            float maxTop = Math.max(maxLeftTop, maxRightTop);
            rect_top = maxTop;
        }

        if (rightShow) {
            rect_right = shadowWidth - shadowRadius;
        } else {
//            rect_right = shadowWidth;
            float maxRightTop = Math.max(cornerRadius, mCornerRadius_rightTop);
            float maxRightBottom = Math.max(cornerRadius, mCornerRadius_rightBottom);
            float maxRight = Math.max(maxRightTop, maxRightBottom);
            rect_right = shadowWidth - maxRight;
        }

        if (bottomShow) {
            rect_bottom = shadowHeight - shadowRadius;
        } else {
//            rect_bottom = shadowHeight;
            float maxLeftBottom = Math.max(cornerRadius, mCornerRadius_leftBottom);
            float maxRightBottom = Math.max(cornerRadius, mCornerRadius_rightBottom);
            float maxBottom = Math.max(maxLeftBottom, maxRightBottom);
            rect_bottom = shadowHeight - maxBottom;
        }


        RectF shadowRect = new RectF(
                rect_left,
                rect_top,
                rect_right,
                rect_bottom);

        if (isSym) {
            if (dy > 0) {
                shadowRect.top += dy;
                shadowRect.bottom -= dy;
            } else if (dy < 0) {
                shadowRect.top += Math.abs(dy);
                shadowRect.bottom -= Math.abs(dy);
            }

            if (dx > 0) {
                shadowRect.left += dx;
                shadowRect.right -= dx;
            } else if (dx < 0) {

                shadowRect.left += Math.abs(dx);
                shadowRect.right -= Math.abs(dx);
            }
        } else {
            shadowRect.top -= dy;
            shadowRect.bottom -= dy;
            shadowRect.right -= dx;
            shadowRect.left -= dx;
        }


        shadowPaint.setColor(fillColor);
        if (!isInEditMode()) {//dx  dy
            shadowPaint.setShadowLayer(shadowRadius / 2, dx, dy, shadowColor);
        }

        if (mCornerRadius_leftBottom == -1 && mCornerRadius_leftTop == -1 && mCornerRadius_rightTop == -1 && mCornerRadius_rightBottom == -1) {
            //如果没有设置整个属性,那么按原始去画
            canvas.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint);
        } else {
            //目前最佳的解决方案
            rectf.left = leftPadding;
            rectf.top = topPadding;
            rectf.right = getWidth() - rightPadding;
            rectf.bottom = getHeight() - bottomPadding;


            shadowPaint.setAntiAlias(true);
            int leftTop;
            if (mCornerRadius_leftTop == -1) {
                leftTop = (int) mCornerRadius / 4;
            } else {
                leftTop = (int) mCornerRadius_leftTop / 4;
            }
            int leftBottom;
            if (mCornerRadius_leftBottom == -1) {
                leftBottom = (int) mCornerRadius / 4;
            } else {
                leftBottom = (int) mCornerRadius_leftBottom / 4;
            }

            int rightTop;
            if (mCornerRadius_rightTop == -1) {
                rightTop = (int) mCornerRadius / 4;
            } else {
                rightTop = (int) mCornerRadius_rightTop / 4;
            }

            int rightBottom;
            if (mCornerRadius_rightBottom == -1) {
                rightBottom = (int) mCornerRadius / 4;
            } else {
                rightBottom = (int) mCornerRadius_rightBottom / 4;
            }

            float[] outerR = new float[]{leftTop, leftTop, rightTop, rightTop, rightBottom, rightBottom, leftBottom, leftBottom};//左上,右上,右下,左下
            Path path = new Path();
            path.addRoundRect(shadowRect, outerR, Path.Direction.CW);
            canvas.drawPath(path, shadowPaint);
        }

        return output;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void dispatchDraw(Canvas canvas) {

        int trueHeight = (int) (rectf.bottom - rectf.top);
        if (getChildAt(0) != null) {
            if (mCornerRadius_leftTop == -1 && mCornerRadius_leftBottom == -1 && mCornerRadius_rightTop == -1 && mCornerRadius_rightBottom == -1) {
                //说明没有设置过任何特殊角、且是半圆。
                if (mCornerRadius > trueHeight / 2) {
                    Path path = new Path();
                    path.addRoundRect(rectf, trueHeight / 2, trueHeight / 2, Path.Direction.CW);
                    canvas.clipPath(path);
                } else {
                    Path path = new Path();
                    path.addRoundRect(rectf, mCornerRadius, mCornerRadius, Path.Direction.CW);
                    canvas.clipPath(path);
                }
            } else {
                float[] outerR = getCornerValue(trueHeight);
                Path path = new Path();
                path.addRoundRect(leftPadding, topPadding, getWidth() - rightPadding, getHeight() - bottomPadding, outerR, Path.Direction.CW);
                canvas.clipPath(path);
            }

        }
        super.dispatchDraw(canvas);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        rectf.left = leftPadding;
        rectf.top = topPadding;
        rectf.right = getWidth() - rightPadding;
        rectf.bottom = getHeight() - bottomPadding;
        int trueHeight = (int) (rectf.bottom - rectf.top);
        //如果都为0说明,没有设置特定角,那么按正常绘制
        if (getChildAt(0) != null) {
            if (mCornerRadius_leftTop == -1 && mCornerRadius_leftBottom == -1 && mCornerRadius_rightTop == -1 && mCornerRadius_rightBottom == -1) {
                if (mCornerRadius > trueHeight / 2) {
                    if (selectorType != 3) {
                        if (layoutBackground == null && layoutBackground_true == null) {
                            //画圆角矩形
                            canvas.drawRoundRect(rectf, trueHeight / 2, trueHeight / 2, paint);
                            //解决边框线太洗时,四角的width偏大和其他边不同
                            if (stroke_color != -101) {
                                int the_height = (int) (rectf.bottom - rectf.top);
                                int the_height_stoke = (int) (rectf.bottom - stroke_with / 2 - rectf.top - stroke_with / 2);
                                int trueCorner = (int) (trueHeight * the_height_stoke / 2 / the_height);

                                RectF rectFStroke = new RectF(rectf.left + stroke_with / 2, rectf.top + stroke_with / 2, rectf.right - stroke_with / 2, rectf.bottom - stroke_with / 2);
                                canvas.drawRoundRect(rectFStroke, trueCorner, trueCorner, paint_stroke);

                            }
                        }
                    } else {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            float[] outerR = getCornerValue(trueHeight);
                            ripple(outerR);
                        }
                    }

                } else {

                    if (selectorType != 3) {
                        if (layoutBackground == null && layoutBackground_true == null) {

                            canvas.drawRoundRect(rectf, mCornerRadius, mCornerRadius, paint);
                            if (stroke_color != -101) {
                                int the_height = (int) (rectf.bottom - rectf.top);
                                int the_height_stoke = (int) (rectf.bottom - stroke_with / 2 - rectf.top - stroke_with / 2);
                                int trueCorner = (int) (mCornerRadius * the_height_stoke / the_height);


                                RectF rectFStroke = new RectF(rectf.left + stroke_with / 2, rectf.top + stroke_with / 2, rectf.right - stroke_with / 2, rectf.bottom - stroke_with / 2);
                                canvas.drawRoundRect(rectFStroke, trueCorner, trueCorner, paint_stroke);

                            }

                        }
                    } else {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            float[] outerR = getCornerValue(trueHeight);
                            ripple(outerR);
                        }
                    }


                }
            } else {
                if (layoutBackground == null && layoutBackground_true == null) {
                    setSpaceCorner(canvas, trueHeight);
                }
            }
        }

    }


    public float[] getCornerValue(int trueHeight) {
        int leftTop;
        int rightTop;
        int rightBottom;
        int leftBottom;
        if (mCornerRadius_leftTop == -1) {
            leftTop = (int) mCornerRadius;
        } else {
            leftTop = (int) mCornerRadius_leftTop;
        }

        if (leftTop > trueHeight / 2) {
            leftTop = trueHeight / 2;
        }

        if (mCornerRadius_rightTop == -1) {
            rightTop = (int) mCornerRadius;
        } else {
            rightTop = (int) mCornerRadius_rightTop;
        }

        if (rightTop > trueHeight / 2) {
            rightTop = trueHeight / 2;
        }

        if (mCornerRadius_rightBottom == -1) {
            rightBottom = (int) mCornerRadius;
        } else {
            rightBottom = (int) mCornerRadius_rightBottom;
        }

        if (rightBottom > trueHeight / 2) {
            rightBottom = trueHeight / 2;
        }


        if (mCornerRadius_leftBottom == -1) {
            leftBottom = (int) mCornerRadius;
        } else {
            leftBottom = (int) mCornerRadius_leftBottom;
        }

        if (leftBottom > trueHeight / 2) {
            leftBottom = trueHeight / 2;
        }

        float[] outerR = new float[]{leftTop, leftTop, rightTop, rightTop, rightBottom, rightBottom, leftBottom, leftBottom};//左上,右上,右下,左下
        return outerR;
    }


    //这里是为了解决stokeWith很大时,圆角盖不住底部四个角的bug(issues #86)
    public float[] getCornerValueOther(int trueHeight, int stokeWith) {
        trueHeight = trueHeight - stokeWith * 2;
        int leftTop;
        int rightTop;
        int rightBottom;
        int leftBottom;
        if (mCornerRadius_leftTop == -1) {
            leftTop = (int) mCornerRadius;
        } else {
            leftTop = (int) mCornerRadius_leftTop;
        }

        if (leftTop > trueHeight / 2) {
            leftTop = trueHeight / 2;
        }

        if (mCornerRadius_rightTop == -1) {
            rightTop = (int) mCornerRadius;
        } else {
            rightTop = (int) mCornerRadius_rightTop;
        }

        if (rightTop > trueHeight / 2) {
            rightTop = trueHeight / 2;
        }

        if (mCornerRadius_rightBottom == -1) {
            rightBottom = (int) mCornerRadius;
        } else {
            rightBottom = (int) mCornerRadius_rightBottom;
        }

        if (rightBottom > trueHeight / 2) {
            rightBottom = trueHeight / 2;
        }


        if (mCornerRadius_leftBottom == -1) {
            leftBottom = (int) mCornerRadius;
        } else {
            leftBottom = (int) mCornerRadius_leftBottom;
        }

        if (leftBottom > trueHeight / 2) {
            leftBottom = trueHeight / 2;
        }
        leftTop = leftTop - stokeWith;
        rightTop = rightTop - stokeWith;
        leftBottom = leftBottom - stokeWith;
        rightBottom = rightBottom - stokeWith;

        float[] outerR = new float[]{leftTop, leftTop, rightTop, rightTop, rightBottom, rightBottom, leftBottom, leftBottom};//左上,右上,右下,左下
        return outerR;
    }


    //这是自定义四个角的方法。
    private void setSpaceCorner(Canvas canvas, int trueHeight) {

        float[] outerR = getCornerValue(trueHeight);

        if (stroke_color != -101) {
            if (selectorType != 3) {
                ShapeDrawable mDrawables = new ShapeDrawable(new RoundRectShape(outerR, null, null));
                if (paint.getShader() != null) {
                    mDrawables.getPaint().setShader(paint.getShader());
                } else {
                    mDrawables.getPaint().setColor(paint.getColor());
                }
                mDrawables.setBounds(leftPadding, topPadding, getWidth() - rightPadding, getHeight() - bottomPadding);
                mDrawables.draw(canvas);

                float[] outerR_stroke = getCornerValueOther(trueHeight, (int) stroke_with);
                ShapeDrawable mDrawablesStroke = new ShapeDrawable(new RoundRectShape(outerR_stroke, null, null));
                mDrawablesStroke.getPaint().setColor(paint_stroke.getColor());
                mDrawablesStroke.getPaint().setStyle(Paint.Style.STROKE);
                mDrawablesStroke.getPaint().setStrokeWidth(stroke_with);
                mDrawablesStroke.setBounds((int) (leftPadding + stroke_with / 2), (int) (topPadding + stroke_with / 2), (int) (getWidth() - rightPadding - stroke_with / 2), (int) (getHeight() - bottomPadding - stroke_with / 2));


                mDrawablesStroke.draw(canvas);
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    ripple(outerR);
                }
            }

        } else {
            if (selectorType != 3) {
                ShapeDrawable mDrawables = new ShapeDrawable(new RoundRectShape(outerR, null, null));
                if (paint.getShader() != null) {
                    mDrawables.getPaint().setShader(paint.getShader());
                } else {
                    mDrawables.getPaint().setColor(paint.getColor());
                }
                mDrawables.setBounds(leftPadding, topPadding, getWidth() - rightPadding, getHeight() - bottomPadding);
                mDrawables.draw(canvas);
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    ripple(outerR);
                }
            }
        }

    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void ripple(float[] outRadius) {

        int[][] stateList = new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{android.R.attr.state_focused},
                new int[]{android.R.attr.state_activated},
                new int[]{}
        };

        //深蓝
        int normalColor = mBackGroundColor;
        //玫瑰红
        int pressedColor = mBackGroundColor_true;
        int[] stateColorList = new int[]{
                pressedColor,
                pressedColor,
                pressedColor,
                normalColor
        };
        ColorStateList colorStateList = new ColorStateList(stateList, stateColorList);

        RoundRectShape roundRectShape = new RoundRectShape(outRadius, null, null);
        ShapeDrawable maskDrawable = new ShapeDrawable();
        maskDrawable.setShape(roundRectShape);
        maskDrawable.getPaint().setStyle(Paint.Style.FILL);
        if (startColor != -101) {
            //如果设置了渐变色的话
            gradient(maskDrawable.getPaint());
        } else {
            maskDrawable.getPaint().setColor(normalColor);
        }

        ShapeDrawable contentDrawable = new ShapeDrawable();
        contentDrawable.setShape(roundRectShape);
        contentDrawable.getPaint().setStyle(Paint.Style.FILL);

        if (startColor != -101) {
            //如果设置了渐变色的话
            gradient(contentDrawable.getPaint());
        } else {
            contentDrawable.getPaint().setColor(normalColor);
        }

        //contentDrawable实际是默认初始化时展示的;maskDrawable 控制了rippleDrawable的范围
        RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, contentDrawable, maskDrawable);
        firstView.setBackground(rippleDrawable);
    }


    public void isAddAlpha(int color) {
        //获取单签颜色值的透明度,如果没有设置透明度,默认加上#2a
        if (Color.alpha(color) == 255) {
            String red = Integer.toHexString(Color.red(color));
            String green = Integer.toHexString(Color.green(color));
            String blue = Integer.toHexString(Color.blue(color));

            if (red.length() == 1) {
                red = "0" + red;
            }

            if (green.length() == 1) {
                green = "0" + green;
            }

            if (blue.length() == 1) {
                blue = "0" + blue;
            }
            String endColor = "#2a" + red + green + blue;
            mShadowColor = convertToColorInt(endColor);
        }
    }


    public static int convertToColorInt(String argb)
            throws IllegalArgumentException {

        if (!argb.startsWith("#")) {
            argb = "#" + argb;
        }

        return Color.parseColor(argb);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (selectorType == 3) {
            //如果是水波纹模式,那么不需要进行下面的渲染,采用系统ripper即可
            if (isClickable) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        if (selectorType == 3) {
                            if (mTextView != null) {
                                mTextView.setTextColor(textColor_true);
                                if (!TextUtils.isEmpty(text_true)) {
                                    mTextView.setText(text_true);
                                }
                            }
                        }
                        break;

                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        if (selectorType == 3) {
                            if (mTextView != null) {
                                mTextView.setTextColor(textColor);
                                if (!TextUtils.isEmpty(text)) {
                                    mTextView.setText(text);
                                }
                            }
                        }
                        break;


                }
            }
            return super.onTouchEvent(event);
        }

        if (mBackGroundColor_true != -101 || stroke_color_true != -101 || layoutBackground_true != null) {
            if (isClickable) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        if (selectorType == 1) {
                            if (mBackGroundColor_true != -101) {
                                paint.setColor(mBackGroundColor_true);
                                //打个标记
                                paint.setShader(null);
                            }
                            if (stroke_color_true != -101) {
                                paint_stroke.setColor(stroke_color_true);
                            }

                            if (layoutBackground_true != null) {
                                setmBackGround(layoutBackground_true);
                            }
                            postInvalidate();

                            if (mTextView != null) {
                                mTextView.setTextColor(textColor_true);
                                if (!TextUtils.isEmpty(text_true)) {
                                    mTextView.setText(text_true);
                                }
                            }
                        }
                        break;

                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        if (selectorType == 1) {
                            //打个标记
                            paint.setColor(mBackGroundColor);
                            if (startColor != -101) {
                                gradient(paint);
                            }
                            if (stroke_color != -101) {
                                paint_stroke.setColor(stroke_color);
                            }

                            if (layoutBackground != null) {
                                setmBackGround(layoutBackground);
                            }
                            postInvalidate();

                            if (mTextView != null) {
                                mTextView.setTextColor(textColor);
                                if (!TextUtils.isEmpty(text)) {
                                    mTextView.setText(text);
                                }
                            }
                        }
                        break;
                }
            }
        }
        return super.onTouchEvent(event);
    }


    public void setmBackGround(Drawable drawable) {
        if (firstView != null && drawable != null) {
            if (mCornerRadius_leftTop == -1 && mCornerRadius_leftBottom == -1 && mCornerRadius_rightTop == -1 && mCornerRadius_rightBottom == -1) {
                GlideRoundManager.setRoundCorner(firstView, drawable, mCornerRadius);
            } else {
                int leftTop;
                if (mCornerRadius_leftTop == -1) {
                    leftTop = (int) mCornerRadius;
                } else {
                    leftTop = (int) mCornerRadius_leftTop;
                }
                int leftBottom;
                if (mCornerRadius_leftBottom == -1) {
                    leftBottom = (int) mCornerRadius;
                } else {
                    leftBottom = (int) mCornerRadius_leftBottom;
                }

                int rightTop;
                if (mCornerRadius_rightTop == -1) {
                    rightTop = (int) mCornerRadius;
                } else {
                    rightTop = (int) mCornerRadius_rightTop;
                }

                int rightBottom;
                if (mCornerRadius_rightBottom == -1) {
                    rightBottom = (int) mCornerRadius;
                } else {
                    rightBottom = (int) mCornerRadius_rightBottom;
                }

                GlideRoundManager.setCorners(firstView, drawable, leftTop, leftBottom, rightTop, rightBottom);
            }
        }
    }
}

//第二部分
package com.mobile.common_library.manager;

import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.View;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.mobile.common_library.custom_view.GlideRoundTransform;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

/**
 * author    : Urasaki
 * e-mail    : 1164688204@qq.com
 * date      : 2021/3/31 10:55
 * introduce :
 */

public class GlideRoundManager {
   
   public static void setRoundCorner(final View view, final Drawable resourceId, final float cornerDipValue) {
      
      if (cornerDipValue == 0) {
         if (view.getMeasuredWidth() == 0 && view.getMeasuredHeight() == 0) {
            view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
               @Override
               public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                  view.removeOnLayoutChangeListener(this);
                  Glide.with(view)
                     .asDrawable()
                     .load(resourceId)
                     .transform(new CenterCrop())
                     .override(view.getMeasuredWidth(), view.getMeasuredHeight())
                     .into(new CustomTarget<Drawable>() {
                        @Override
                        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                           if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                              view.setBackgroundDrawable(resource);
                           } else {
                              view.setBackground(resource);
                           }
                           
                        }
                        
                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        
                        }
                     });
               }
            });
         } else {
            Glide.with(view)
               .asDrawable()
               .load(resourceId)
               .transform(new CenterCrop())
               .override(view.getMeasuredWidth(), view.getMeasuredHeight())
               .into(new CustomTarget<Drawable>() {
                  @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                  @Override
                  public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                     if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                        view.setBackgroundDrawable(resource);
                     } else {
                        view.setBackground(resource);
                     }
                  }
                  
                  @Override
                  public void onLoadCleared(@Nullable Drawable placeholder) {
                  
                  }
               });
         }
         
      } else {
         
         if (view.getMeasuredWidth() == 0 && view.getMeasuredHeight() == 0) {
            view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
               @Override
               public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                  view.removeOnLayoutChangeListener(this);
                  Glide.with(view)
                     .load(resourceId)
                     .transform(new CenterCrop(), new RoundedCorners((int) cornerDipValue))
                     .override(view.getMeasuredWidth(), view.getMeasuredHeight())
                     .into(new CustomTarget<Drawable>() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                        @Override
                        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                           if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                              view.setBackgroundDrawable(resource);
                           } else {
                              view.setBackground(resource);
                           }
                        }
                        
                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        
                        }
                     });
               }
            });
         } else {
            Glide.with(view)
               .load(resourceId)
               .transform(new CenterCrop(), new RoundedCorners((int) cornerDipValue))
               .override(view.getMeasuredWidth(), view.getMeasuredHeight())
               .into(new CustomTarget<Drawable>() {
                  @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                  @Override
                  public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                     if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                        view.setBackgroundDrawable(resource);
                     } else {
                        view.setBackground(resource);
                     }
                  }
                  
                  @Override
                  public void onLoadCleared(@Nullable Drawable placeholder) {
                  
                  }
               });
         }
         
      }
      
   }
   
   public static void setCorners(final View view, final Drawable resourceId, final float leftTop_corner, final float leftBottom_corner, final float rightTop_corner, final float rightBottom_corner) {
      if (leftTop_corner == 0 && leftBottom_corner == 0 && rightTop_corner == 0 && rightBottom_corner == 0) {
         if (view.getMeasuredWidth() == 0 && view.getMeasuredHeight() == 0) {
            view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
               @Override
               public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                  view.removeOnLayoutChangeListener(this);
                  Glide.with(view)
                     .load(resourceId)
                     .override(view.getMeasuredWidth(), view.getMeasuredHeight())
                     .into(new CustomTarget<Drawable>() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                        @Override
                        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                           if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                              view.setBackgroundDrawable(resource);
                           } else {
                              view.setBackground(resource);
                           }
                        }
                        
                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        
                        }
                     });
               }
            });
         } else {
            Glide.with(view)
               .load(resourceId)
               .override(view.getMeasuredWidth(), view.getMeasuredHeight())
               .into(new CustomTarget<Drawable>() {
                  @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                  @Override
                  public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                     if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                        view.setBackgroundDrawable(resource);
                     } else {
                        view.setBackground(resource);
                     }
                  }
                  
                  @Override
                  public void onLoadCleared(@Nullable Drawable placeholder) {
                  
                  }
               });
         }
         
      } else {
         if (view.getMeasuredWidth() == 0 && view.getMeasuredHeight() == 0) {
            view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
               @Override
               public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                  view.removeOnLayoutChangeListener(this);
                  GlideRoundTransform transform = new GlideRoundTransform(view.getContext(), leftTop_corner, leftBottom_corner, rightTop_corner, rightBottom_corner);
                  Glide.with(view)
                     .load(resourceId)
                     .transform(transform)
                     .override(view.getMeasuredWidth(), view.getMeasuredHeight())
                     .into(new CustomTarget<Drawable>() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                        @Override
                        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                           if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                              view.setBackgroundDrawable(resource);
                           } else {
                              view.setBackground(resource);
                           }
                        }
                        
                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        
                        }
                     });
               }
            });
         } else {
            
            GlideRoundTransform transform = new GlideRoundTransform(view.getContext(), leftTop_corner, leftBottom_corner, rightTop_corner, rightBottom_corner);
            Glide.with(view)
               .load(resourceId)
               .transform(transform)
               .override(view.getMeasuredWidth(), view.getMeasuredHeight())
               .into(new CustomTarget<Drawable>() {
                  @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                  @Override
                  public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                     if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                        view.setBackgroundDrawable(resource);
                     } else {
                        view.setBackground(resource);
                     }
                  }
                  
                  @Override
                  public void onLoadCleared(@Nullable Drawable placeholder) {
                  
                  }
               });
            
         }
         
      }
      
   }
   
}

 

2.使用。

<net.p5w.console.custom_view.ShadowLinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginStart="@dimen/dp_2"
    android:layout_marginEnd="@dimen/dp_2"
    android:orientation="vertical"
    app:hl_cornerRadius="@dimen/dp_7"
    app:hl_shadowColor="#2a000000"
    app:hl_shadowHiddenBottom="false"
    app:hl_shadowHiddenLeft="false"
    app:hl_shadowHiddenRight="false"
    app:hl_shadowHiddenTop="false"
    app:hl_shadowLimit="@dimen/dp_12">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <View
            android:layout_width="@dimen/dp_8"
            android:layout_height="@dimen/dp_10" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rcv_sub_workbench"
            android:layout_width="@dimen/dp_316"
            android:layout_height="wrap_content" />

        <View
            android:layout_width="@dimen/dp_8"
            android:layout_height="@dimen/dp_10" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_17"
        tools:ignore="UselessLeaf" />

</net.p5w.console.custom_view.ShadowLinearLayout>

 

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现阴影可以使用以下两种方法: 1. 使用CardView实现阴影 CardView是一个常用的控件,它可以帮我们简单地实现阴影效果。CardView是在Android 5.0之后才引入的,如果应用的最低支持版本小于5.0,则需要在build.gradle文件中添加依赖库: ```java implementation 'com.android.support:cardview-v7:28.0.0' ``` 在布局文件中加入CardView控件,并设置相关属性即可实现阴影效果: ```xml <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:elevation="6dp" card_view:cardCornerRadius="4dp" card_view:cardBackgroundColor="#ffffff"> <!-- 在这里添加需要显示的内容 --> </android.support.v7.widget.CardView> ``` 2. 使用自定义Drawable实现阴影 自定义Drawable是一种更加灵活的方式,可以实现更加个性化的阴影效果。通过在Drawable设置不同的形状和颜色,可以实现不同的阴影效果。下面是一个简单的实现示例: ```xml <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/shadow"> <!-- 在这里添加需要显示的内容 --> </RelativeLayout> ``` 在drawable文件夹下新建shadow.xml文件,实现自定义Drawable: ```xml <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#ffffff" /> <corners android:radius="5dp" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> <size android:height="1dp" /> <gradient android:startColor="@android:color/transparent" android:endColor="#88000000" android:angle="90" /> </shape> ``` 在这个示例中,我们设置了一个圆角矩形,并为其设置了白色背景、边距、高度和渐变色阴影。根据自己的需求可以调整不同的属性,实现不同的阴影效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值