天天看點

View繪制系列(14)-Paint混合模式

Paint混合模式

前文中我們在繪制時所有的坐标都是經過精确計算的,但是在現實應用場景中,我們不能百分之百的保證所繪制的每個圖像都是獨立互不相交的,我們也有可能會遇到下圖中的情形:

View繪制系列(14)-Paint混合模式

這時可能需要保留重合區域,也有可能保留其他區域,怎麼去定制呢?使用XferMode即可。

關于

Paint.setXferMode

的官網說明如下:

Set or clear the transfer mode object. A transfer mode defines how source pixels (generate by a drawing command) are composited with the destination pixels (content of the render target).

PorterDuffXfermode is the most common transfer mode.

其是用來設定混合模式(直譯過渡模式)的,混合模式指的是使用

Canvas

繪圖方法繪制的元素與畫布上已有内容的渲染組合方式。

PorterDuffXfermode

是最常用的混合模式對象。

PorterDuffXfermode

隻有一個含參的構造函數

PorterDuffXfermode(PorterDuff.Mode mode)

,

mode

可選值有:

  • PorterDuff.Mode.CLEAR

  • PorterDuff.Mode.SRC

  • PorterDuff.Mode.DST

  • PorterDuff.Mode.SRC_OVER

  • PorterDuff.Mode.DST_OVER

  • PorterDuff.Mode.SRC_IN

  • PorterDuff.Mode.DST_IN

  • PorterDuff.Mode.SRC_OUT

  • PorterDuff.Mode.DST_OUT

  • PorterDuff.Mode.SRC_ATOP

  • PorterDuff.Mode.DST_ATOP

  • PorterDuff.Mode.XOR

  • PorterDuff.Mode.DARKEN

  • PorterDuff.Mode.LIGHTEN

  • PorterDuff.Mode.MULTIPLY

  • PorterDuff.Mode.SCREEN

  • PorterDuff.Mode.ADD

  • PorterDuff.Mode.OVERLAY

我們看到在這些混合模式中有

SRC

DST

的區分,

DST

指的是先繪制的原始圖檔,

SRC

指的是我們将應用混合模式繪制的新圖檔,使用

XferMode

時應注意在新圖層或者畫布上做操作,在

Android

中常見的畫布擷取方式有兩種:

  • onDraw

    函數中的

    canvas

    對象,在這裡明顯不适用
  • 使用

    Bitmap

    構造

    Canvas

    對象,相當于對

    Bitmap

    對象進行繪制

這裡我們使用

Bitmap

的方式擷取畫布,并在該畫布上進行

XferMode

的混合工作,完成後将

Bitmap

使用

canvas.drawBitmap

繪制在自定義

View

内,完整的

onDraw

代碼如下:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //擷取先繪制的Bitmap對象,即DST Bitmap
    Bitmap dstBitmap = makeDst(getWidth()/2,getWidth()/2);
    //擷取采用混合模式繪制的Bitmap對象,即SRC bitmap
    Bitmap srcBitmap = makeSrc(getWidth(),getWidth()/2);

    //使用Bitmap方式擷取畫布,建立一個和View大小相同的Bitmap對象
    Bitmap bitmap = createBitamp(getWidth(), getHeight());
    Canvas resultCanvas = new Canvas(bitmap);
    //擷取Bitmap的Canvas畫布對象
    Paint xfermodePaint = new Paint();
    //使用Bitmap的畫布對象繪制DST bitmap
    resultCanvas.drawBitmap(dstBitmap, 0, 0, xfermodePaint);
    //依次修改這裡的PorterDuff.Mode.ADD為CLEAR...得到下表
    xfermodePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
    //使用混合模式将SRC bitmap繪制到Bitmap的畫布内
    resultCanvas.drawBitmap(srcBitmap, 0, 0, xfermodePaint);

    Paint paint = new Paint();
    //繪制混合結果到View上
    canvas.drawBitmap(bitmap,0,0,paint);
}

    //建立一個圓形bitmap,作為dst圖
    private Bitmap makeDst(int width, int height) {
        Bitmap bm = createBitamp(width, height);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        c.drawOval(new RectF(0, 0, width / 3 * 2, height / 3 * 2), p);
        return bm;
    }

    // 建立一個矩形bitmap,作為src圖
    private Bitmap makeSrc(int width, int height) {
        Bitmap bm = createBitamp(width, height);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFF66AAFF);
        c.drawRect(100, 100, width, height, p);
        return bm;
    }

    private Bitmap createBitamp(int w, int h){
        return Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    }
           

複制

依次使用

PorterDuffXfermode

的各模式繪制效果,見下表:

View繪制系列(14)-Paint混合模式