一個簡單的自定義CircleDrawable,實現(xiàn)圓形頭像效果

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>

__*

<a title="點(diǎn)擊顯示原始圖片">
</a>

Demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容