基于PorterDuffXfermode或Shader绘制圆角图片

  1. 基于PorterDuffXfermode方式
    这里写图片描述
    canvas原有的图片可以理解为背景,就是dst;
    新画上去的图片可以理解为前景,就是src。
/**
 * Created by star on 2016/6/15
 * 功能:基于PorterDuffXfermode的圆角图片
 */
public class RoundRectImageView extends ImageView {
    private int type;
    private int radius;
    private int strokeWidth;
    private int strokeColor;
    private Paint strokePaint;
    private Paint paint;
    private Paint blankPaint;
    private RectF rect;
    private RectF rectPath;

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

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

    public RoundRectImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundRectImageView, defStyleAttr, 0);
        radius = (int) a.getDimension(R.styleable.RoundRectImageView_mradius,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics()));
        type = a.getInt(R.styleable.RoundRectImageView_type, 0);
        strokeWidth = (int) a.getDimension(R.styleable.RoundRectImageView_stroke_width, 0);
        strokeColor = a.getColor(R.styleable.RoundRectImageView_stroke_color, getResources().getColor(R.color.white));
        a.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //保存图层
        int sc = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
        //绘制图片
        super.onDraw(canvas);
        if (paint == null) {
            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        }
        int sc2 = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), paint, Canvas.ALL_SAVE_FLAG);
        if (blankPaint == null) {
            blankPaint = new Paint();
            blankPaint.setAntiAlias(true);
            blankPaint.setColor(Color.TRANSPARENT);
            blankPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        }
        canvas.drawColor(Color.BLACK);
        if (type == 0) {
            createRoundImage(canvas);
        } else {
            createRectImage(canvas);
        }
        canvas.restoreToCount(sc2);
        canvas.restoreToCount(sc);

        if (strokeWidth > 0) {
            if (strokePaint == null) {
                strokePaint = new Paint();
                strokePaint.setAntiAlias(true);
                strokePaint.setColor(strokeColor);
                strokePaint.setStrokeWidth(strokeWidth);
                strokePaint.setStyle(Paint.Style.STROKE);
            }
            if (type == 0) {
                radius = Math.min(canvas.getWidth() / 2, canvas.getHeight() / 2) - strokeWidth / 2;
                canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, radius, strokePaint);
            } else {
                if (rectPath == null) {
                    rectPath = new RectF(strokeWidth / 2, strokeWidth / 2, canvas.getWidth() - strokeWidth / 2, canvas.getHeight() - strokeWidth / 2);
                }
                canvas.drawRoundRect(rectPath, radius - strokeWidth / 2, radius - strokeWidth / 2, strokePaint);
            }
        }
    }

    private void createRectImage(Canvas canvas) {
        int min = Math.min(canvas.getWidth() / 2, canvas.getHeight() / 2);
        if (radius >= min) {
            type = 0;
        }
        radius = Math.min(min, radius);
        rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
        canvas.drawRoundRect(rect, radius, radius, blankPaint);
    }

    private void createRoundImage(Canvas canvas) {
        radius = Math.min(canvas.getWidth(), canvas.getHeight());
        canvas.drawCircle(radius / 2, radius / 2, radius / 2, blankPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        rect = null;
    }
}

<declare-styleable name="RoundRectImageView">
        <attr name="mradius" format="dimension"/>
        <attr name="type">
            <enum name="round" value="0"/>
            <enum name="rect" value="1"/>
        </attr>
        <attr name="stroke_width" format="dimension"/>
        <attr name="stroke_color" format="color"/>
    </declare-styleable>
  1. 基于Shader模式的
/**
 * Created by star on 2016/6/16
 * 功能:
 */
public class ShaderRoundRectImageView extends ImageView {
    //显示类型
    private int type;
    //圆角
    private int radius;
    //描边宽度
    private int strokeWidth;
    //描边颜色
    private int strokeColor;

    //描边画笔
    private Paint strokePaint;
    //描边路径
    private RectF rectPath;

    //缩放矩阵
    private Matrix matrix;
    //图像画笔
    private Paint bitmapPaint;
    //渲染
    private BitmapShader bitmapShader;
    //图像路径
    private RectF roundRect;
    //图像宽度
    private int width;

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

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

    public ShaderRoundRectImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        matrix = new Matrix();
        bitmapPaint = new Paint();
        bitmapPaint.setAntiAlias(true);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundRectImageView, defStyleAttr, 0);
        radius = (int) a.getDimension(R.styleable.RoundRectImageView_mradius,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics()));
        type = a.getInt(R.styleable.RoundRectImageView_type, 0);
        strokeWidth = (int) a.getDimension(R.styleable.RoundRectImageView_stroke_width, 0);
        strokeColor = a.getColor(R.styleable.RoundRectImageView_stroke_color, getResources().getColor(R.color.white));
        a.recycle();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //如果是圆形的话,强制使宽高一直,选取最小的
        if (type == 0) {
            width = Math.min(getMeasuredWidth(), getMeasuredHeight());
            radius = width / 2;
            setMeasuredDimension(width, width);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }
        setUpShader();
        if (type == 0) {
            canvas.drawCircle(radius, radius, radius, bitmapPaint);
        } else {
            canvas.drawRoundRect(roundRect, radius, radius, bitmapPaint);
        }

        if (strokeWidth > 0) {
            if (strokePaint == null) {
                strokePaint = new Paint();
                strokePaint.setColor(strokeColor);
                strokePaint.setAntiAlias(true);
                strokePaint.setStrokeWidth(strokeWidth);
                strokePaint.setStyle(Paint.Style.STROKE);
            }
            if (type == 0) {
                radius -= strokeWidth / 2;
                canvas.drawCircle(width / 2, width / 2, radius, strokePaint);
            } else {
                canvas.drawRoundRect(rectPath, radius - strokeWidth / 2, radius - strokeWidth / 2, strokePaint);
            }
        }
    }

    /**
     * 给画笔设置Shader
     */
    private void setUpShader() {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }
        Bitmap bitmap = drawableToBitmap(drawable);
        if (bitmapShader == null) {
            //拉伸模式的Shader
            bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        }
        float scale = 1.0f;
        if (type == 0) {
            //按照图像的最小的边进行缩放
            int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
            scale = width * 1.0f / bSize;
        } else {
            //取最大的缩放比例,其实也是按照最小边进行缩放
            scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f / bitmap.getHeight());
        }
        matrix.setScale(scale, scale);
        bitmapShader.setLocalMatrix(matrix);
        bitmapPaint.setShader(bitmapShader);
    }

    /**
     * 将drawable转化为bitmap
     *
     * @param drawable
     * @return
     */
    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (type == 1) {
            roundRect = new RectF(0, 0, w, h);
            if (strokeWidth > 0) {
                rectPath = new RectF(strokeWidth / 2, strokeWidth / 2, w - strokeWidth / 2, h - strokeWidth / 2);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值