【ImageView】自定義ImageView系列(一)——簡(jiǎn)單圓形圖片

Android項(xiàng)目開發(fā)中經(jīng)常會(huì)遇見需要實(shí)現(xiàn)圓角或者圓形的圖片功能,如果僅僅使用系統(tǒng)自帶的ImageView控件顯然無(wú)法實(shí)現(xiàn)此功能,故通過(guò)系列文章的形式由簡(jiǎn)到繁全方位的介紹一下此功能的實(shí)現(xiàn),鞏固一下自身的學(xué)習(xí),同時(shí),和廣大網(wǎng)友交流分享。

自定義圓形ImageView.jpg

作為第一篇文章,今天通過(guò)一些簡(jiǎn)單的代碼介紹一下圓形圖片功能的初步實(shí)現(xiàn)。

自定義的ImageView控件代碼如下,如果擁有一定的Android自定義View基礎(chǔ)知識(shí)的話,通過(guò)查看注釋基本上能夠看懂實(shí)現(xiàn)過(guò)程:

package com.feng.meiya.widget.imageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CircleImageView extends ImageView {

    //基本的三個(gè)構(gòu)造函數(shù)
    public CircleImageView(Context context) {
        super(context);
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    //自定義View實(shí)現(xiàn)過(guò)程中很重要的onDraw繪制圖形的方法
    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();

        //空值判斷,必要步驟,避免由于沒(méi)有設(shè)置src導(dǎo)致的異常錯(cuò)誤
        if (drawable == null) {
            return;
        }

        //必要步驟,避免由于初始化之前導(dǎo)致的異常錯(cuò)誤
        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }

        if (!(drawable instanceof BitmapDrawable)) {
            return;
        }
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();

        if (null == b) {
            return;
        }

        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth();

        Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

    /**
     * 初始Bitmap對(duì)象的縮放裁剪過(guò)程
     * @param bmp       初始Bitmap對(duì)象
     * @param radius    圓形圖片直徑大小
     * @return 返回一個(gè)圓形的縮放裁剪過(guò)后的Bitmap對(duì)象
     */
    public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
        Bitmap sbmp;
        //比較初始Bitmap寬高和給定的圓形直徑,判斷是否需要縮放裁剪Bitmap對(duì)象
        if (bmp.getWidth() != radius || bmp.getHeight() != radius)
            sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
        else
            sbmp = bmp;
        Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),
                Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f,
                sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
        //核心部分,設(shè)置兩張圖片的相交模式,在這里就是上面繪制的Circle和下面繪制的Bitmap
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(sbmp, rect, rect, paint);

        return output;
    }

}

其中一個(gè)很重要的地方就是Paint.setXfermode(Xfermode xfermode)方法,設(shè)置兩圖的相交模式,這里只作簡(jiǎn)單的介紹:

系統(tǒng)提供的Xfermode子類有三個(gè):

  • AvoidXfermode
    指定了一個(gè)顏色和容差,強(qiáng)制Paint避免在它上面繪圖(或者只在它上面繪圖)。

  • PixelXorXfermode
    當(dāng)覆蓋已有的顏色時(shí),應(yīng)用一個(gè)簡(jiǎn)單的像素XOR操作。

  • PorterDuffXfermode
    這是一個(gè)非常強(qiáng)大的轉(zhuǎn)換模式,使用它,可以使用圖像合成的16條Porter-Duff規(guī)則的任意一條來(lái)控制Paint如何與已有的Canvas圖像進(jìn)行交互。

常用用法如下:

Canvas canvas = new Canvas(bitmap1);   
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));   
canvas.drawBitmap(mask, 0f, 0f, paint);

可以簡(jiǎn)單理解為,canvas原有的圖片就是背景,即dst, 新畫上去的圖片就是前景,即src,這樣,不同的Mode展示效果如下:

PorterDuffXfermode兩圖相交模式效果

看完上圖大致就能理解本文中自定義ImageView實(shí)現(xiàn)圓形圖片的原理了,下一篇將以GitHub中比較成熟的開源項(xiàng)目為例介紹一個(gè)功能全面、性能優(yōu)化的CircleImageView控件的實(shí)現(xiàn)過(guò)程,歡迎關(guān)注。

歡迎關(guān)注鳥哥微信公眾號(hào)【技術(shù)鳥】,掌握最新技術(shù)動(dòng)態(tài)!

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

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

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