基于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.0 f;
if (type == 0 ) {
int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
scale = width * 1.0 f / bSize;
} else {
scale = Math.max(getWidth() * 1.0 f / bitmap.getWidth(), getHeight() * 1.0 f / 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 );
}
}
}
}