Github上有一个star5000+的CircleImageView,代码设计得十分简洁流畅,其实通过自定义一个Drawable也完全可以实现这个效果。(ps:其实是今天在看源码的时候,在Setting模块看到了一个类似的CircleFramedDrawable~,自己几乎没有修改就能实现圆形图片的效果)。
因为代码十分简单,所以一些简单分析就直接写在注释里了。这里只说一下实现思路:通过为画笔设置PorterDuff.Mode,来让新建的圆形图层与原Bitmap只显示重合部分。(PorterDuff.Mode:一个强大的图像转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。哈哈,说人话就是用来控制图层与图层之间如何覆盖,覆盖之后取哪部分显示到画布上,有兴趣的可以自行百度,这里只用到了两种模式。)
下面直接上代码和效果图:
在构造方法里处理图层关系:
public CircleFramedDrawable(Bitmap icon, int size) {
super();
mSize = size;
mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(mBitmap);
final int width = icon.getWidth();
final int height = icon.getHeight();
final int square = Math.min(width, height);
final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
final Path fillPath = new Path();
//path.addArc方法用于绘制圆弧,这个圆弧取自RectF矩形的内接椭圆上的一部分,圆弧长度由后两个角度参数决定
fillPath.addArc(circleRect, 0f, 360f);
//PorterDuff.Mode.CLEAR:清除画布(所绘制不会提交到画布上)
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
// opaque circle matte
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(fillPath, mPaint);
// mask in the icon where the bitmap is opaque(不透明)
//PorterDuff.Mode.SRC_IN:两者相交的地方绘制源图
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
// prepare paint for frame drawing
// 别忘记还原画笔~
mPaint.setXfermode(null);
mScale = 1f;
mSrcRect = new Rect(0, 0, mSize, mSize);
mDstRect = new RectF(0, 0, mSize, mSize);
}
当然支持图片的缩放啦:
@Override
public void draw(Canvas canvas) {
//缩放处理
final float inside = mScale * mSize;
final float pad = (mSize - inside) / 2f;
//将矩形的坐标设置为缩放后指定的值
mDstRect.set(pad, pad, mSize - pad, mSize - pad);
//第一个mSrcRect代表要绘制的bitmap区域,第二个mDstRect代表的是要将bitmap绘制在屏幕的什么地方
canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
}
获取drawable时传入我们想要的大小就可以了
public static CircleFramedDrawable getInstance(Context context, Bitmap icon,float size) {
Resources res = context.getResources();
float iconSize = px2dip(context,size);
CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
return instance;
}
怎么使用?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.workingdog);
mIcon.setImageDrawable(CircleFramedDrawable.getInstance(this,bitmap,800));
}
所以可以不用修改项目中的布局文件,直接加一个Drawable类就能在任何时候转换图片至圆形了!
效果图:
__*
Demo地址