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
的各模式繪制效果,見下表: