现在很多App的头像都使用圆形来展示,于是自己想了想如何去实现,先在网上搜了下资料,其核心是通过设置Paint的PorterDuffXfermode 合成模式来实现。先来了解下PorterDuffXfermode 的合成模式(图片来自网上):
Src为原图,Dst为目标图,图片显示的是先绘制目标图,然后设置Xfermode,再绘制Src后的效果。有13种不同的合成模式,我们看SrcIn和DstIn,绘制原图和目标图后,最终显示的是两者的交集,SrcIn留下的是Src,DstIn留下的是Dst。我们可以考虑下,一张方形图与圆形图,通过设置交集模式,最终就是一张圆形图。这里就有两种方法可以实现:
第一种是先绘制圆形图,然后设置Paint的合成模式为SrcIn,再将bitmap画上去;
第二种是先绘制bitmap,然后设置Paint的合成模式为DstIn,再将圆形图画上去;
下面是代码的实现步骤:
1、继承ImageView,在onSizeChanged里面获取控件的宽高,重写onDraw方法;
2、在onDraw方法里面,首先要对图片进行压缩,压缩比例为控件的宽高与bitmap宽高的比例;
3、新建一个与控件宽高一致的canvas,并新建paint,在canvas上画一个实心圆;
4、画完圆之后,需要设置paint的颜色混合模式PorterDuff.Mode.SRC_IN,然后再将压缩后的bitmap画上去;
下面是具体的实现代码:
public class RoundImageView extends ImageView {
private int height;//控件高
private int width;//控件宽
private Bitmap bitmap;//原图
private int srcWidth;//图宽
private int srcHeight;//图高
private int radius;//圆半径
private Bitmap scaleBitmap;//原图缩放后的图
private Bitmap bitmap2;//圆形图
private Canvas canvas1;//画圆形图的画布
private Paint paint;//画笔
public RoundImageView(Context context) {
super(context);
}
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
height = h;
width = w;
radius = Math.min(h, w) / 2;
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
super.onDraw(canvas);
return;
}
if (!(drawable instanceof BitmapDrawable)) {
return;
}
bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap == null) return;
srcWidth = bitmap.getWidth();
srcHeight = bitmap.getHeight();
//缩放图片
scaleBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
bitmap2 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas1 = new Canvas(bitmap2);
paint = new Paint();
paint.setAntiAlias(true);//抗锯齿
paint.setDither(true);//防抖动
paint.setFilterBitmap(true);//对位图进行滤波处理
canvas1.drawCircle(width / 2, height / 2, radius, paint);//圆心x坐标、y坐标,半径,画笔
//设置像素颜色的混合模式,此模式为取交集
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas1.drawBitmap(scaleBitmap, 0, 0, paint);
canvas.drawBitmap(bitmap2, 0, 0, null);
}
}
现在就可以使用这个自定义的圆形ImageView了。