绘制流程:
1.根据获取的属性值,判断显示模式,并设置圆形图片、外边框、内边框的半径值
2.画边框
3.画图片内容
(1)获取原图
(2)得到正方形图
(3)得到缩放图
(4)得到圆形图
public class MyRoundImageView extends ImageView { private int defaultColor = 0xffffffff; private ShowType mShowType = ShowType.NoBorder; private int mBorderThickness = 0; private int mBorderInsideColor; private int mBorderOutsideColor; private int mRadius = 0; enum ShowType { InsideBorder, OutsideBorder, InsideAndOutsideBorder, NoBorder } public MyRoundImageView(Context context) { super(context); } public MyRoundImageView(Context context, AttributeSet attrs) { super(context, attrs); readAttrs(attrs); } public MyRoundImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); readAttrs(attrs); } private void readAttrs(AttributeSet attrs) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RoundImageView); mBorderThickness = a.getDimensionPixelSize(R.styleable.RoundImageView_border_thickness, 0); mBorderInsideColor = a.getColor(R.styleable.RoundImageView_border_inside_color, defaultColor); mBorderOutsideColor = a.getColor(R.styleable.RoundImageView_border_outside_color, defaultColor); readShowType(); } private void readShowType() { if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) { mShowType = ShowType.InsideAndOutsideBorder; } else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) { mShowType = ShowType.InsideBorder; } else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) { mShowType = ShowType.OutsideBorder; } else { mShowType = ShowType.NoBorder; } } @Override protected void onDraw(Canvas canvas) { switch (mShowType) { case InsideBorder: mRadius = (getWidth() < getHeight() ? getWidth() : getHeight()) / 2 - mBorderThickness; drawRoundBorder(canvas, mRadius + mBorderThickness / 2, mBorderInsideColor); break; case OutsideBorder: mRadius = (getWidth() < getHeight() ? getWidth() : getHeight()) / 2 - mBorderThickness; drawRoundBorder(canvas, mRadius + mBorderThickness / 2, mBorderOutsideColor); break; case InsideAndOutsideBorder: mRadius = (getWidth() < getHeight() ? getWidth() : getHeight()) / 2 - mBorderThickness * 2; drawRoundBorder(canvas, mRadius + mBorderThickness / 2, mBorderInsideColor); drawRoundBorder(canvas, mRadius + mBorderThickness / 2 + mBorderThickness, mBorderOutsideColor); break; case NoBorder: mRadius = (getWidth() < getHeight() ? getWidth() : getHeight()) / 2; break; default: } drawBitmapContent(canvas); } private void drawRoundBorder(Canvas canvas, int radius, int color) { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(color); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mBorderThickness); canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, paint); } private void drawBitmapContent(Canvas canvas) { canvas.drawBitmap(bitmapToRound(bitmapToScale(bitmapToSquare(readBitmap()))), getWidth() / 2 - mRadius, getHeight() / 2 - mRadius, null); } private Bitmap readBitmap() { Drawable drawable = getDrawable(); if (drawable == null) { return null; } if (drawable instanceof NinePatchDrawable) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap().copy(Bitmap.Config.ARGB_8888, true); } return null; } private Bitmap bitmapToSquare(Bitmap bitmap) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int x = w > h ? (w - h) / 2 : 0; int y = w > h ? 0 : (h - w) / 2; int sideLength = w > h ? h : w; return Bitmap.createBitmap(bitmap, 0, 0, sideLength, sideLength); } private Bitmap bitmapToScale(Bitmap bitmap) { return Bitmap.createScaledBitmap(bitmap, mRadius * 2, mRadius * 2, true); } public Bitmap bitmapToRound(Bitmap bitmap) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); Rect rect = new Rect(0, 0, output.getWidth(),output.getHeight()); paint.setAntiAlias(true); canvas.drawRoundRect(new RectF(rect), rect.width()/2, rect.height()/2, paint); //取output的图层与bitmap的图层的交集 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //参数2是截取原图区域,可以不是全部图片,参数3是显示位置区域 canvas.drawBitmap(bitmap, rect, rect, paint); return output; } }
附1.设置两张图片相交时的模式
/** * setXfermode 设置两张图片相交时的模式 */ // PorterDuff.Mode.CLEAR 清除画布上图像 // PorterDuff.Mode.SRC 显示上层图像 // PorterDuff.Mode.DST 显示下层图像 // PorterDuff.Mode.SRC_OVER上下层图像都显示,上层居上显示 // PorterDuff.Mode.DST_OVER 上下层都显示,下层居上显示 // PorterDuff.Mode.SRC_IN 取两层图像交集部门,只显示上层图像 // PorterDuff.Mode.DST_IN 取两层图像交集部门,只显示下层图像 // PorterDuff.Mode.SRC_OUT 取上层图像非交集部门 // PorterDuff.Mode.DST_OUT 取下层图像非交集部门 // PorterDuff.Mode.SRC_ATOP 取下层图像非交集部门与上层图像交集部门 // PorterDuff.Mode.DST_ATOP 取上层图像非交集部门与下层图像交集部门 // PorterDuff.Mode.XOR 取两层图像的非交集部门