Android自定义View——可设置形状(圆形、圆角矩形、椭圆)的ImageView,抗锯齿

效果如下:


全部代码:【ShapeImageView】

package xiaodan.www.amor_love.Utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
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.net.Uri;
import android.provider.MediaStore;
import android.util.AttributeSet;

import xiaodan.www.amor_love.R;

/**
 * 可设置形状的ImageView,抗边缘锯齿
 *
 * @author 冯人唐
 */
public class ShapeImageView extends android.support.v7.widget.AppCompatImageView {
    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 2;

    //系统数据库存放图片的路径
    private static final Uri STORAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    public static int SHAPE_REC = 1; // 矩形
    public static int SHAPE_CIRCLE = 2; // 圆形
    public static int SHAPE_OVAL = 3; // 椭圆
    private final Matrix mShaderMatrix = new Matrix();
    private float mBorderSize = 0; // 边框大小,默认为0,即无边框
    private int mBorderColor = Color.WHITE; // 边框颜色,默认为白色
    private int mShape = SHAPE_REC; // 形状,默认为直接矩形
    private float mRoundRadius = 0; // 矩形的圆角半径,默认为0,即直角矩形
    private float mRoundRadiusLeftTop, mRoundRadiusLeftBottom, mRoundRadiusRightTop, mRoundRadiusRightBottom;
    private Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private RectF mViewRect = new RectF(); // imageview的矩形区域
    private RectF mBorderRect = new RectF(); // 边框的矩形区域
    private Paint mBitmapPaint = new Paint();
    private BitmapShader mBitmapShader;
    private Bitmap mBitmap;
    private Path mPath = new Path();

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

    public ShapeImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle); // 虽然此处会调用setImageDrawable,但此时成员变量还未被正确初始化
        init(attrs);
        mBorderPaint.setStyle(Style.STROKE);
        mBorderPaint.setStrokeWidth(mBorderSize);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setAntiAlias(true);
        mBitmapPaint.setAntiAlias(true);
        super.setScaleType(ScaleType.CENTER_CROP); // 固定为CENTER_CROP,其他不生效
    }

    private void init(AttributeSet attrs) {

        TypedArray a = getContext().obtainStyledAttributes(attrs,
                R.styleable.ShapeImageView);
        mShape = a.getInt(R.styleable.ShapeImageView_siv_shape, mShape);
        mRoundRadius = a.getDimension(R.styleable.ShapeImageView_siv_round_radius, mRoundRadius);
        mBorderSize = a.getDimension(R.styleable.ShapeImageView_siv_border_size, mBorderSize);
        mBorderColor = a.getColor(R.styleable.ShapeImageView_siv_border_color, mBorderColor);

        mRoundRadiusLeftBottom = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_leftBottom, mRoundRadius);
        mRoundRadiusLeftTop = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_leftTop, mRoundRadius);
        mRoundRadiusRightBottom = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_rightBottom, mRoundRadius);
        mRoundRadiusRightTop = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_rightTop, mRoundRadius);

        a.recycle();

        SelectorAttrs.obtainsAttrs(getContext(), this, attrs);
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setupBitmapShader();
    }

    public Bitmap getBitmapFromDrawable(Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        try {
            Bitmap bitmap;

            if (drawable instanceof ColorDrawable) {
                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
            } else {
                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
            }

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private void setupBitmapShader() {
        // super(context, attrs, defStyle)调用setImageDrawable时,成员变量还未被正确初始化
        if (mBitmapPaint == null) {
            return;
        }
        if (mBitmap == null) {
            invalidate();
            return;
        }
        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mBitmapPaint.setShader(mBitmapShader);

        // 固定为CENTER_CROP,使图片在view中居中并裁剪
        mShaderMatrix.set(null);
        // 缩放到高或宽 与view的高或宽 匹配
        float scale = Math.max(getWidth() * 1f / mBitmap.getWidth(), getHeight() * 1f / mBitmap.getHeight());
        // 由于BitmapShader默认是从画布的左上角开始绘制,所以把其平移到画布中间,即居中
        float dx = (getWidth() - mBitmap.getWidth() * scale) / 2;
        float dy = (getHeight() - mBitmap.getHeight() * scale) / 2;
        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate(dx, dy);
        mBitmapShader.setLocalMatrix(mShaderMatrix);
        invalidate();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap = getBitmapFromDrawable(drawable);
        setupBitmapShader();
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (scaleType != ScaleType.CENTER_CROP) {
            throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
        }
    }

    /**
     * 对于普通的view,在执行到onDraw()时,背景图已绘制完成
     * <p>
     * 对于ViewGroup,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,
     * 当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用,
     */
    @Override
    public void onDraw(Canvas canvas) {

        if (mBitmap != null) {
            if (mShape == SHAPE_CIRCLE) {
                canvas.drawCircle(mViewRect.right / 2, mViewRect.bottom / 2,
                        Math.min(mViewRect.right, mViewRect.bottom) / 2, mBitmapPaint);
            } else if (mShape == SHAPE_OVAL) {
                canvas.drawOval(mViewRect, mBitmapPaint);
            } else {
//                canvas.drawRoundRect(mViewRect, mRoundRadius, mRoundRadius, mBitmapPaint);
                mPath.reset();
                mPath.addRoundRect(mViewRect, new float[]{
                        mRoundRadiusLeftTop, mRoundRadiusLeftTop,
                        mRoundRadiusRightTop, mRoundRadiusRightTop,
                        mRoundRadiusRightBottom, mRoundRadiusRightBottom,
                        mRoundRadiusLeftBottom, mRoundRadiusLeftBottom,
                }, Path.Direction.CW);
                canvas.drawPath(mPath, mBitmapPaint);

            }
        }

        if (mBorderSize > 0) { // 绘制边框
            if (mShape == SHAPE_CIRCLE) {
                canvas.drawCircle(mViewRect.right / 2, mViewRect.bottom / 2,
                        Math.min(mViewRect.right, mViewRect.bottom) / 2 - mBorderSize / 2, mBorderPaint);
            } else if (mShape == SHAPE_OVAL) {
                canvas.drawOval(mBorderRect, mBorderPaint);
            } else {
//                canvas.drawRoundRect(mBorderRect, mRoundRadius, mRoundRadius, mBorderPaint);
                mPath.reset();
                mPath.addRoundRect(mBorderRect, new float[]{
                        mRoundRadiusLeftTop, mRoundRadiusLeftTop,
                        mRoundRadiusRightTop, mRoundRadiusRightTop,
                        mRoundRadiusRightBottom, mRoundRadiusRightBottom,
                        mRoundRadiusLeftBottom, mRoundRadiusLeftBottom,
                }, Path.Direction.CW);
                canvas.drawPath(mPath, mBorderPaint);
            }
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        initRect();
        setupBitmapShader();
    }

    // 不能在onLayout()调用invalidate(),否则导致绘制异常。(setupBitmapShader()中调用了invalidate())
    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
                            int bottom) {
        super.onLayout(changed, left, top, right, bottom);
//        initRect();
//        setupBitmapShader();
    }

    // 设置图片的绘制区域
    private void initRect() {

        mViewRect.top = 0;
        mViewRect.left = 0;
        mViewRect.right = getWidth(); // 宽度
        mViewRect.bottom = getHeight(); // 高度

        // 边框的矩形区域不能等于ImageView的矩形区域,否则边框的宽度只显示了一半
        mBorderRect.top = mBorderSize / 2;
        mBorderRect.left = mBorderSize / 2;
        mBorderRect.right = getWidth() - mBorderSize / 2;
        mBorderRect.bottom = getHeight() - mBorderSize / 2;
    }

    public int getShape() {
        return mShape;
    }

    public void setShape(int shape) {
        mShape = shape;
    }

    public float getBorderSize() {
        return mBorderSize;
    }

    public void setBorderSize(int mBorderSize) {
        this.mBorderSize = mBorderSize;
        mBorderPaint.setStrokeWidth(mBorderSize);
        initRect();
        invalidate();
    }

    public int getBorderColor() {
        return mBorderColor;
    }

    public void setBorderColor(int mBorderColor) {
        this.mBorderColor = mBorderColor;
        mBorderPaint.setColor(mBorderColor);
        invalidate();
    }

    public float getRoundRadius() {
        return mRoundRadius;
    }

    public void setRoundRadius(float mRoundRadius) {
        this.mRoundRadius = mRoundRadius;
        invalidate();
    }

    public void setRoundRadiis(float roundRadiusLeftBottom, float roundRadiusLeftTop, float roundRadiusRightBottom, float roundRadiusRightTop) {
        mRoundRadiusLeftBottom = roundRadiusLeftBottom;
        mRoundRadiusLeftTop = roundRadiusLeftTop;
        mRoundRadiusRightBottom = roundRadiusRightBottom;
        mRoundRadiusRightTop = roundRadiusRightTop;
        invalidate();
    }

    public float[] getRoundRadiis() {
        return new float[]{mRoundRadiusLeftBottom, mRoundRadiusLeftTop, mRoundRadiusRightBottom, mRoundRadiusRightTop};
    }

}

工具类【SelectorAttrs】

package xiaodan.www.amor_love.Utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.view.View;

import xiaodan.www.amor_love.R;

/**
 * 冯人唐
 */
public class SelectorAttrs {

    public static final int RECTANGLE = 0;

    public static final int OVAL = 1;

    public static final int LINE = 2;

    public static final int RING = 3;

    /**
     * 直接在布局文件中直接设置selector
     *
     * @param context
     * @param view
     * @param attrs
     */
    public static void obtainsAttrs(Context context, View view, AttributeSet attrs) {

        //背景已经设置为StateListDrawable\RippleDrawable,则不再设置Selector
        Drawable bitmapDrawable = view.getBackground();
        if (bitmapDrawable instanceof StateListDrawable) {
            return;
        }
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            if (bitmapDrawable instanceof RippleDrawable) {
                return;
            }
        }

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.View);

        // 背景图片和背景颜色互斥,只能设置其中之一

        if (bitmapDrawable instanceof ColorDrawable) { // 颜色值
            bitmapDrawable = null;
        }

        // 用于设置背景的颜色和形状
        GradientDrawable colorShapeDrawable = null;
        GradientDrawable colorShapeDrawablePressed = null;
        GradientDrawable colorShapeDrawableSelected = null;

        // 用于设置背景的图片
        Drawable bitmapDrawablePressed = null;
        Drawable bitmapDrawableSelected = null;

        if (a.hasValue(R.styleable.View_sel_background_pressed) || a.hasValue(R.styleable.View_sel_background_border_pressed)) {
            bitmapDrawablePressed = a.getDrawable(R.styleable.View_sel_background_pressed);
            if (bitmapDrawablePressed instanceof ColorDrawable) {
                bitmapDrawablePressed = null;
            }
            if (bitmapDrawablePressed == null) { // 接下来设置背景颜色
                colorShapeDrawablePressed = new GradientDrawable();
            }
        }
        if (a.hasValue(R.styleable.View_sel_background_selected) || a.hasValue(R.styleable.View_sel_background_border_selected)) {
            bitmapDrawableSelected = a.getDrawable(R.styleable.View_sel_background_selected);
            if (bitmapDrawableSelected instanceof ColorDrawable) {
                bitmapDrawableSelected = null;
            }
            if (bitmapDrawableSelected == null) {
                colorShapeDrawableSelected = new GradientDrawable();
            }
        }

        // 设置背景色
        int background = Color.TRANSPARENT;
        if (bitmapDrawable == null) {
            Drawable bg = view.getBackground();
            if (bg == null && a.hasValue(R.styleable.View_sel_background)) { // 兼容旧版本属性
                bg = a.getDrawable(R.styleable.View_sel_background);
            }
            colorShapeDrawable = new GradientDrawable();
            if (bg instanceof ColorDrawable) {
                background = ((ColorDrawable) bg).getColor();
                colorShapeDrawable.setColor(background);
            }
        }
        if (colorShapeDrawablePressed != null) {
            colorShapeDrawablePressed.setColor(background);
        }
        if (colorShapeDrawableSelected != null) {
            colorShapeDrawableSelected.setColor(background);
        }

        // 形狀
        int shape = a.getInt(R.styleable.View_sel_background_shape, RECTANGLE);
        if (shape == LINE) {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setShape(GradientDrawable.LINE);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setShape(GradientDrawable.LINE);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setShape(GradientDrawable.LINE);
            }
        } else if (shape == OVAL) {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setShape(GradientDrawable.OVAL);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setShape(GradientDrawable.OVAL);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setShape(GradientDrawable.OVAL);
            }
        } else if (shape == RING) {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setShape(GradientDrawable.RING);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setShape(GradientDrawable.RING);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setShape(GradientDrawable.RING);
            }
        } else {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setShape(GradientDrawable.RECTANGLE);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setShape(GradientDrawable.RECTANGLE);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setShape(GradientDrawable.RECTANGLE);
            }
        }

        // 圆角
        int backgroundCorners = a.getDimensionPixelOffset(R.styleable.View_sel_background_corners, 0);
        final int radius = backgroundCorners;
        if (colorShapeDrawable != null) {
            colorShapeDrawable.setCornerRadius(backgroundCorners);
        }
        if (colorShapeDrawablePressed != null) {
            colorShapeDrawablePressed.setCornerRadius(backgroundCorners);
        }
        if (colorShapeDrawableSelected != null) {
            colorShapeDrawableSelected.setCornerRadius(backgroundCorners);
        }

        final int topLeftRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_corner_topLeft, radius);
        final int topRightRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_corner_topRight, radius);
        final int bottomLeftRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_corner_bottomLeft, radius);
        final int bottomRightRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_corner_bottomRight, radius);
        if (topLeftRadius != radius || topRightRadius != radius ||
                bottomLeftRadius != radius || bottomRightRadius != radius) {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setCornerRadii(new float[]{
                        topLeftRadius, topLeftRadius,
                        topRightRadius, topRightRadius,
                        bottomRightRadius, bottomRightRadius,
                        bottomLeftRadius, bottomLeftRadius
                });
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setCornerRadii(new float[]{
                        topLeftRadius, topLeftRadius,
                        topRightRadius, topRightRadius,
                        bottomRightRadius, bottomRightRadius,
                        bottomLeftRadius, bottomLeftRadius
                });
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setCornerRadii(new float[]{
                        topLeftRadius, topLeftRadius,
                        topRightRadius, topRightRadius,
                        bottomRightRadius, bottomRightRadius,
                        bottomLeftRadius, bottomLeftRadius
                });
            }
        }


        // border
        int backgroundBorderWidth = a.getDimensionPixelOffset(R.styleable.View_sel_background_border_width, -1);
        if (backgroundBorderWidth != -1) {
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setStroke(backgroundBorderWidth, 0);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setStroke(backgroundBorderWidth, 0);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setStroke(backgroundBorderWidth, 0);
            }
        }

        if (a.hasValue(R.styleable.View_sel_background_border_color)) {
            int backgroundBorder = a.getColor(R.styleable.View_sel_background_border_color, -1);
            if (colorShapeDrawable != null) {
                colorShapeDrawable.setStroke(backgroundBorderWidth, backgroundBorder);
            }
            if (colorShapeDrawablePressed != null) {
                colorShapeDrawablePressed.setStroke(backgroundBorderWidth, backgroundBorder);
            }
            if (colorShapeDrawableSelected != null) {
                colorShapeDrawableSelected.setStroke(backgroundBorderWidth, backgroundBorder);
            }
        }

        // 如果没有设置背景图片,则读取背景颜色
        if (colorShapeDrawablePressed != null && a.hasValue(R.styleable.View_sel_background_pressed)) {
            int backgroundPressed = a.getColor(R.styleable.View_sel_background_pressed, 0);
            colorShapeDrawablePressed.setColor(backgroundPressed);
        }
        if (colorShapeDrawablePressed != null && a.hasValue(R.styleable.View_sel_background_border_pressed)) {
            int backgroundBorderPressed = a.getColor(R.styleable.View_sel_background_border_pressed, -1);
            colorShapeDrawablePressed.setStroke(backgroundBorderWidth, backgroundBorderPressed);
        }
        if (colorShapeDrawableSelected != null && a.hasValue(R.styleable.View_sel_background_selected)) {
            int backgroundSelected = a.getColor(R.styleable.View_sel_background_selected, -1);
            colorShapeDrawableSelected.setColor(backgroundSelected);
        }
        if (colorShapeDrawableSelected != null && a.hasValue(R.styleable.View_sel_background_border_selected)) {
            int backgroundBorderSelected = a.getColor(R.styleable.View_sel_background_border_selected, -1);
            colorShapeDrawableSelected.setStroke(backgroundBorderWidth, backgroundBorderSelected);
        }


        // 设置不同状态下的显示
        StateListDrawable stateListDrawable = new StateListDrawable();
        // ripple属性兼容低版本(<21)
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP // 低于21(5.0)版本
                && a.hasValue(R.styleable.View_sel_background_ripple)) { // 但设置了ripple,处理兼容则把ripple的颜色设为按下时的颜色

            Drawable drawable = null;
            if (a.hasValue(R.styleable.View_sel_background_ripple_mask)) { // 根据mask设置形状
                drawable = a.getDrawable(R.styleable.View_sel_background_ripple_mask);
                if (drawable instanceof ColorDrawable) { // mask为颜色类型才可以设置形状
                    drawable = new GradientDrawable();
                    parseRippleMaskShape((GradientDrawable) drawable, a);
                    // 以sel_background_ripple的颜色为准
                    ((GradientDrawable) drawable).setColor(a.getColor(R.styleable.View_sel_background_ripple, 0));
                } else {
                    drawable = a.getDrawable(R.styleable.View_sel_background_ripple);
                }
            } else {
                drawable = a.getDrawable(R.styleable.View_sel_background_ripple);
            }

            // ripple效果只是在原来的pressed基础上附加波纹效果,并不会单独作为pressed状态的效果
            if (colorShapeDrawablePressed != null || bitmapDrawablePressed != null) {
                drawable = new LayerDrawable(new Drawable[]{
                        bitmapDrawablePressed != null ? bitmapDrawablePressed : colorShapeDrawablePressed,
                        drawable
                });
            } else if (bitmapDrawable != null || colorShapeDrawable != null) {
                drawable = new LayerDrawable(new Drawable[]{
                        bitmapDrawable != null ? bitmapDrawable : colorShapeDrawable,
                        drawable
                });
            }
            stateListDrawable.addState(
                    new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, drawable);
        } else if (colorShapeDrawablePressed != null || bitmapDrawablePressed != null) {
            Drawable drawable = bitmapDrawablePressed != null ? bitmapDrawablePressed : colorShapeDrawablePressed;
            stateListDrawable.addState(
                    new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, drawable);
        }

        if (colorShapeDrawableSelected != null || bitmapDrawableSelected != null) {
            Drawable drawable = bitmapDrawableSelected != null ? bitmapDrawableSelected : colorShapeDrawableSelected;
            stateListDrawable.addState(
                    new int[]{android.R.attr.state_enabled, android.R.attr.state_selected}, drawable);
        }
        stateListDrawable.addState(
                new int[]{},
                bitmapDrawable != null ? bitmapDrawable : colorShapeDrawable);


        // 设置ripple水波纹
        boolean hasRipple = parseRipple(view, a,
                // ripple效果只是在原来的pressed基础上附加波纹效果,并不会单独作为pressed状态的效果
                (colorShapeDrawable != null || bitmapDrawable != null
                        || colorShapeDrawablePressed != null || bitmapDrawablePressed != null) ?
                        stateListDrawable : null);

        if (!hasRipple) {
            view.setBackgroundDrawable(stateListDrawable);
        }
        a.recycle();
    }

    private static void parseRippleMaskShape(GradientDrawable maskShapeDrawable, TypedArray a) {
        // 必须设置颜色
        maskShapeDrawable.setColor(a.getColor(R.styleable.View_sel_background_ripple_mask, Color.TRANSPARENT));

        // Mask形状
        int shape = a.getInt(R.styleable.View_sel_background_ripple_mask_shape, RECTANGLE);
        if (shape == LINE) {
            maskShapeDrawable.setShape(GradientDrawable.LINE);
        } else if (shape == OVAL) {
            maskShapeDrawable.setShape(GradientDrawable.OVAL);
        } else if (shape == RING) {
            maskShapeDrawable.setShape(GradientDrawable.RING);
        } else {
            maskShapeDrawable.setShape(GradientDrawable.RECTANGLE);
        }

        // mask圆角
        int backgroundCorners = a.getDimensionPixelOffset(R.styleable.View_sel_background_ripple_mask_corners, 0);
        final int radius = backgroundCorners;
        maskShapeDrawable.setCornerRadius(backgroundCorners);

        final int topLeftRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_ripple_mask_corner_topLeft, radius);
        final int topRightRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_ripple_mask_corner_topRight, radius);
        final int bottomLeftRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_ripple_mask_corner_bottomLeft, radius);
        final int bottomRightRadius = a.getDimensionPixelSize(
                R.styleable.View_sel_background_ripple_mask_corner_bottomRight, radius);
        if (topLeftRadius != radius || topRightRadius != radius ||
                bottomLeftRadius != radius || bottomRightRadius != radius) {
            maskShapeDrawable.setCornerRadii(new float[]{
                    topLeftRadius, topLeftRadius,
                    topRightRadius, topRightRadius,
                    bottomRightRadius, bottomRightRadius,
                    bottomLeftRadius, bottomLeftRadius
            });
        }
    }

    private static boolean parseRipple(View view, TypedArray a, Drawable content) {
        // 设置ripple水波纹
        boolean hasRipple = false;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            if (a.hasValue(R.styleable.View_sel_background_ripple)) {
                hasRipple = true;
                // 设置了背景则作为ripple的contentDrawable

                // 用于设置mask的形状
                GradientDrawable maskShapeDrawable = null;
                // 用于设置mask的图片
                Drawable maskBitmapDrawable = null;

                if (a.hasValue(R.styleable.View_sel_background_ripple_mask)) {
                    maskBitmapDrawable = a.getDrawable(R.styleable.View_sel_background_ripple_mask);
                    if (maskBitmapDrawable instanceof ColorDrawable) {
                        maskBitmapDrawable = null;
                    }
                    if (maskBitmapDrawable == null) { // 接下来设置mask形状
                        maskShapeDrawable = new GradientDrawable();
                        parseRippleMaskShape(maskShapeDrawable, a);
                    }
                }
                RippleDrawable rippleDrawable = new RippleDrawable(
                        a.getColorStateList(R.styleable.View_sel_background_ripple),
                        content, maskBitmapDrawable != null ? maskBitmapDrawable : maskShapeDrawable);

                view.setBackgroundDrawable(rippleDrawable);
            }
        }
        return hasRipple;
    }
}

之后在values的文件夹下面新建“attrs.xml”文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ShapeImageView">
        <attr name="siv_shape" format="enum">
            <enum name="rect" value="1" />
            <enum name="circle" value="2" />
            <enum name="oval" value="3" />
        </attr>
        <attr name="siv_round_radius" format="dimension" />
        <attr name="siv_round_radius_leftTop" format="dimension" />
        <attr name="siv_round_radius_leftBottom" format="dimension" />
        <attr name="siv_round_radius_rightTop" format="dimension" />
        <attr name="siv_round_radius_rightBottom" format="dimension" />
        <attr name="siv_border_size" format="dimension" />
        <attr name="siv_border_color" format="color" />
    </declare-styleable>
    <!-- 设置view相关selector熟悉-->
    <declare-styleable name="View">

        <attr name="injectListener" format="boolean" />

        <!--该属性已过时,被废弃-->
        <attr name="sel_background" format="color" />

        <!-- 背景状态 -->
        <attr name="sel_background_pressed" format="reference|color" />
        <attr name="sel_background_selected" format="reference|color" />

        <!-- 背景形状 -->
        <attr name="sel_background_shape" format="enum">
            <enum name="rect" value="0" />
            <enum name="oval" value="1" />
            <enum name="line" value="2" />
            <enum name="ring" value="3" />
        </attr>
        <!-- 背景圆角 -->
        <attr name="sel_background_corners" format="dimension" />
        <attr name="sel_background_corner_topLeft" format="dimension" />
        <attr name="sel_background_corner_topRight" format="dimension" />
        <attr name="sel_background_corner_bottomLeft" format="dimension" />
        <attr name="sel_background_corner_bottomRight" format="dimension" />

        <!-- 背景边框默认状态 -->
        <attr name="sel_background_border_color" format="color" />
        <attr name="sel_background_border_width" format="dimension" />
        <!-- 背景边框状态 -->
        <attr name="sel_background_border_pressed" format="color" />
        <attr name="sel_background_border_selected" format="color" />

        <!-- ripple水波纹效果-->
        <attr name="sel_background_ripple" format="reference|color" />
        <attr name="sel_background_ripple_mask" format="reference|color" />
        <!-- ripple mask形状(仅在sel_background_ripple_mask为color时生效)-->
        <attr name="sel_background_ripple_mask_shape" format="enum">
            <enum name="rect" value="0" />
            <enum name="oval" value="1" />
            <enum name="line" value="2" />
            <enum name="ring" value="3" />
        </attr>
        <!-- ripple mask圆角 -->
        <attr name="sel_background_ripple_mask_corners" format="dimension" />
        <attr name="sel_background_ripple_mask_corner_topLeft" format="dimension" />
        <attr name="sel_background_ripple_mask_corner_topRight" format="dimension" />
        <attr name="sel_background_ripple_mask_corner_bottomLeft" format="dimension" />
        <attr name="sel_background_ripple_mask_corner_bottomRight" format="dimension" />
    </declare-styleable>
</resources>
大功告成,可以在布局里面用了


猜你喜欢

转载自blog.csdn.net/fengyenom1/article/details/80136149