Github上有一個star5000+的CircleImageView,代碼設(shè)計得十分簡潔流暢,其實通過自定義一個Drawable也完全可以實現(xiàn)這個效果。(ps:其實是今天在看源碼的時候,在Setting模塊看到了一個類似的CircleFramedDrawable~,自己幾乎沒有修改就能實現(xiàn)圓形圖片的效果)。
因為代碼十分簡單,所以一些簡單分析就直接寫在注釋里了。這里只說一下實現(xiàn)思路:通過為畫筆設(shè)置PorterDuff.Mode,來讓新建的圓形圖層與原Bitmap只顯示重合部分。(PorterDuff.Mode:一個強(qiáng)大的圖像轉(zhuǎn)換模式,使用它,可以使用圖像合成的16條Porter-Duff規(guī)則的任意一條來控制Paint如何與已有的Canvas圖像進(jìn)行交互。哈哈,說人話就是用來控制圖層與圖層之間如何覆蓋,覆蓋之后取哪部分顯示到畫布上,有興趣的可以自行百度,這里只用到了兩種模式。)
下面直接上代碼和效果圖:
在構(gòu)造方法里處理圖層關(guān)系:
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矩形的內(nèi)接橢圓上的一部分,圓弧長度由后兩個角度參數(shù)決定
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);
}
當(dāng)然支持圖片的縮放啦:
@Override
public void draw(Canvas canvas) {
//縮放處理
final float inside = mScale * mSize;
final float pad = (mSize - inside) / 2f;
//將矩形的坐標(biāo)設(shè)置為縮放后指定的值
mDstRect.set(pad, pad, mSize - pad, mSize - pad);
//第一個mSrcRect代表要繪制的bitmap區(qū)域,第二個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類就能在任何時候轉(zhuǎn)換圖片至圓形了!
效果圖:
<a title="點(diǎn)擊顯示原始圖片">
</a>
__*
