【Android】PorterDuffXfermode混合效果

(1)Xfermode概述

  • Xfermode是一種將所繪制的圖形的像素按照一定模式進行混合從而形成新的像素值
  • 基本有以下幾種形式,左圖是官網(wǎng)提供的,代碼導致理解有誤差,以右圖為準

<a name="1zF5m"></a>

(2)默認效果

  • 后繪制的覆蓋前面繪制的
public class MyView extends View {

    private static final int SIZE = 200;

    private Paint mPaint;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(2);
    }

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

        // 背景色
        canvas.drawARGB(255, 255, 156, 161);

        // 畫圓
        mPaint.setColor(0xFFFF0000);
        canvas.drawCircle(SIZE / 2, SIZE / 2, SIZE / 2, mPaint);

        // 畫矩形
        mPaint.setColor(0xFF00FF00);
        canvas.drawRect(SIZE / 2, SIZE / 2, SIZE * 3 / 2, SIZE * 3 / 2, mPaint);
    }
}

<a name="PLqBj"></a>

(3)layer圖層理解

  • 不設置默認情況下,后面繪制的覆蓋老的
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 背景色
        canvas.drawARGB(255, 255, 156, 161);

        // 畫圓
        mPaint.setColor(0xFFFF0000);
        canvas.drawCircle(SIZE / 2, SIZE / 2, SIZE / 2, mPaint);

        // 畫矩形
        mPaint.setColor(0xFF00FF00);
        canvas.drawRect(SIZE / 2, SIZE / 2, SIZE * 3 / 2, SIZE * 3 / 2, mPaint);
    }
  • PorterDuff.Mode.CLEAR:同一個圖層重合的部分會被置為透明(此時Activity的背景就是黑色)


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

        // 背景色
        canvas.drawARGB(255, 255, 156, 161);

        // 畫圓
        mPaint.setColor(0xFFFF0000);
        canvas.drawCircle(SIZE / 2, SIZE / 2, SIZE / 2, mPaint);

        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        // 畫矩形
        mPaint.setColor(0xFF00FF00);
        canvas.drawRect(SIZE / 2, SIZE / 2, SIZE * 3 / 2, SIZE * 3 / 2, mPaint);
        
        mPaint.setXfermode(null);
    }
  • 圖層理解

1、canvas默認就有一個layer,默認都繪制在這個圖層上
2、canvas.saveLayer()可以新建一個layer,新建的layer放置在canvas默認layer的上部,之后我們所有的繪制操作都繪制到了我們新建的圖層上,默認這個圖層是透明的
3、canvas.saveLayer()方法會返回一個int值,用于表示layer的ID,在我們對這個新layer繪制完成后可以通過調(diào)用canvas.restoreToCount(layer)或者canvas.restore()把這個layer繪制到canvas默認的layer上去,這樣就完成了一個layer的繪制工作。

image.png
  • 背景顏色在默認圖層
  • 圓形和方形在新建圖層,混合模式為CLEAR,最終效果顯示為3/4圓
  • 圖層合并后顯示如上
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 背景色
        canvas.drawARGB(255, 255, 156, 161);

        // 新建一個圖層
        int saveLayer = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);

        // 畫圓
        mPaint.setColor(0xFFFF0000);
        canvas.drawCircle(SIZE / 2, SIZE / 2, SIZE / 2, mPaint);

        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        // 畫矩形
        mPaint.setColor(0xFF00FF00);
        canvas.drawRect(SIZE / 2, SIZE / 2, SIZE * 3 / 2, SIZE * 3 / 2, mPaint);

        mPaint.setXfermode(null);

        // 將新建的圖層繪制到默認圖層上
        canvas.restoreToCount(saveLayer);
    }

<a name="Kzo01"></a>

(4)混合效果嘗試

  • 測試代碼,修改PorterDuff模式
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 背景色
        canvas.drawARGB(255, 255, 156, 161);

        int saveLayer = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);

        // 畫圓
        mPaint.setColor(0xFFFF0000);
        canvas.drawCircle(SIZE / 2, SIZE / 2, SIZE / 2, mPaint);


        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        // 畫矩形
        mPaint.setColor(0xFF00FF00);
        canvas.drawRect(SIZE / 2, SIZE / 2, SIZE * 3 / 2, SIZE * 3 / 2, mPaint);

        mPaint.setXfermode(null);
        canvas.restoreToCount(saveLayer);
    }
  • 混合模式

1.PorterDuff.Mode.CLEAR:清空混合區(qū)域,變?yōu)槿该?br> 2.PorterDuff.Mode.SRC:顯示上層繪制圖片,下層也顯示
3.PorterDuff.Mode.DST:只顯示下層繪制圖片
4.PorterDuff.Mode.SRC_OVER:正常繪制顯示,上下層繪制疊蓋。
5.PorterDuff.Mode.DST_OVER:上下層都顯示。下層居上顯示。
6.PorterDuff.Mode.SRC_IN:取兩層繪制交集。顯示上層。
7.PorterDuff.Mode.DST_IN:取兩層繪制交集。顯示下層。
8.PorterDuff.Mode.SRC_OUT:取上層繪制非交集部分。顯示下層
9.PorterDuff.Mode.DST_OUT:取下層繪制非交集部分。不顯示上層
10.PorterDuff.Mode.SRC_ATOP:取下層非交集部分與上層交集部分
11.PorterDuff.Mode.DST_ATOP:取上層非交集部分與下層交集部分
12.PorterDuff.Mode.XOR:異或:去除兩圖層交集部分
13.PorterDuff.Mode.DARKEN:取兩圖層全部區(qū)域,交集部分顏色加深
14.PorterDuff.Mode.LIGHTEN:取兩圖層全部,點亮交集部分顏色
15.PorterDuff.Mode.MULTIPLY:取兩圖層交集部分疊加后顏色
16.PorterDuff.Mode.SCREEN:取兩圖層全部區(qū)域,交集部分變?yōu)橥该魃?/p>

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

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