- 基于PorterDuffXfermode方式
canvas原有的图片可以理解为背景,就是dst;
新画上去的图片可以理解为前景,就是src。
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>
- 基于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) {
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);
}
}
}
}