PorterDuffXfermode 正确使用方式(详解)

这里写图片描述

正确姿势中:黄色的为先画的 即下层 蓝色的为后画的 即上层

SRC是上层 dst是下层 in是交集 out是 不想交的

举例:PorterDuff.Mode.SRC_IN参数,表示的是取两层绘制交集。显示上层

核心原理(边界):

图一(正确姿势):两张bitmap已手机宽高为例 边界:宽高既是手机的宽高 所以 里面连个图形 不透明与不透明颜色相交 不相交的 在边界里用叠加模式 所以和左边给的效果是一致的

图二(平时的误解):一个bitmap drawCircle 的两个 所以边界是我画的两个矩形 注意 :边界就是是第层的区域 边界内用叠加模式去弄 边界之外不用叠加模式 所以会变成这样
SrcIn的时候

例子:这里所有的注释 都是非常重要的 所以都需要去用心的看!!!(我认为的~)
github上的代码演示->动画、surfaceView、绘图方面的研究->Xfermode->选择mode
https://github.com/luhaoaimama1/ZoneStudio/blob/master/Android_Zone_Test/src/com/example/mylib_test/activity/animal/viewa/XfermodeView.java

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        onDrawFinal(canvas);
    }
    private void onDrawFinal(Canvas canvas) {
        if (mode!=null) {
            paint.reset();
//都好使
//            bitmapXfermodeExample1(canvas);
            graphXfermodeExample2(canvas);
        }
    }
    //这种对应情况图2
    private void graphXfermodeExample2(Canvas canvas) {
        //为什么这么写savelayer因为 super.draw会又底图层  想要与底层不干扰 不叠加需要save或者 直接画bitmap
        //但是画bitmap的画 那个bitmap又需要一个新的画布去叠加 所以savelayer最快了!!!!
        //这两种都行
//        canvas.saveLayer(0, 0, getWidth(), getHeight(), paint,Canvas.ALL_SAVE_FLAG);
        canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 255,
                Canvas.ALL_SAVE_FLAG);
        paint.setColor(Color.YELLOW);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, 200, paint);
        paint.setXfermode(new PorterDuffXfermode(mode));
        paint.setColor(Color.BLUE);
        canvas.drawCircle(getWidth() / 2 + 200, getHeight() / 2 + 200, 200, paint);
//        canvas.restoreToCount(1);//可以不用  按道理多图层应该是会用到!!!但是不知道为啥不用也好使!!!
    }
    //这种对应情况图1
    private void bitmapXfermodeExample1(Canvas canvas) {
        Canvas canvas2=new Canvas();
        //画黄色的圆 满屏幕那种 bitmap
        Bitmap bt = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
        canvas2.setBitmap(bt);
        paint.setColor(Color.YELLOW);
        canvas2.drawCircle(getWidth() / 2, getHeight() / 2, 200, paint);
        //画蓝色的圆 满屏幕那种 bitmap
        Bitmap bt2 = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
        canvas2.setBitmap(bt2);
        paint.setColor(Color.BLUE);
        canvas2.drawCircle(getWidth() / 2 + 200, getHeight() / 2 + 200, 200, paint);
//--------可用1 bitmap叠加 最简单的------------------------------------------------------------------------------------------------
//        canvas2.setBitmap(bt);
//        paint.setXfermode(new PorterDuffXfermode(mode));
//        canvas2.drawBitmap(bt2, 0, 0, paint);
//        //如果canvas.draw的时候 这句话是必须的 因为系统super.draw会绘制一个图层如果不制空叠加模式 会导致混乱的
//        paint.setXfermode(null);
//        //最后用画布展现出那个最终合成的bitmap
//        canvas.drawBitmap(bt, 0, 0, paint);
//--------可用1 结束------------------------------------------------------------------------------------------------
//--------可用2  bitmap叠加   最後发现模式和 setBitmap和此相当  并且 叠加模式可以在draw上用而且可以的不是一次
//        Bitmap bt3 = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
//        canvas2=new Canvas(bt3);
//        canvas2.drawBitmap(bt, 0, 0, paint);
//        paint.setXfermode(new PorterDuffXfermode(mode));
//        canvas2.drawBitmap(bt2, 0, 0, paint);
//        paint.setXfermode(null);
//        canvas.drawBitmap(bt3, 0, 0, paint);
//--------可用2 结束------------------------------------------------------------------------------------------------
//--------可用3  第二图层layer 叠加
//        paint.setXfermode(null);//此行要注意 super.draw也会话的 如果用叠加模式 会混乱的 当然默认模式是null 如果没写过 可以不写此行
//        canvas.saveLayer(0, 0, getWidth(), getHeight(), paint,
//                Canvas.ALL_SAVE_FLAG);
//        canvas.drawBitmap(bt, 0, 0, paint);
//        paint.setXfermode(new PorterDuffXfermode(mode));
//        canvas.drawBitmap(bt2, 0, 0, paint);
//        canvas.restoreToCount(1);//可以不用  按道理多图层应该是会用到!!!但是不知道为啥不用也好使!!!
//--------可用3 结束------------------------------------------------------------------------------------------------
//--------可用4  多图层layer 叠加
//        paint.setXfermode(null);//此行要注意 super.draw也会话的 如果用叠加模式 会混乱的 当然默认模式是null 如果没写过 可以不写此行
        canvas.saveLayer(0, 0, getWidth(), getHeight(), paint,
                Canvas.ALL_SAVE_FLAG);
        canvas.drawBitmap(bt, 0, 0, paint);
        paint.setXfermode(new PorterDuffXfermode(mode));
        //注意这里savelayer的paint 是有叠加模式的!!!!!!!!!!!!!!!!!
        canvas.saveLayer(0, 0, getWidth(), getHeight(), paint,
                Canvas.ALL_SAVE_FLAG);
        paint.setXfermode(null);//注意这里需要吧叠加模式制空 不然会与layer的空位图 进行叠加
        canvas.drawBitmap(bt2, 0, 0, paint);
//        canvas.restoreToCount(1);//可以不用  按道理多图层应该是会用到!!!但是不知道为啥不用也好使!!!
//--------可用4 结束-------------------------------------------------------------------
    }

setXfermode的注意

1 paint.setXfermode(null);
… 2和1相互作用
2 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
… 这个之间的算2的 都与1相互作用
3 paint.setXfermode(null);
… 4和3 相互作用
4 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

layer入栈出栈的理解

这个出栈:restore,restoreToCount但Layer入栈时,后续的DrawXXX操作都发生在这个Layer上,而Layer退栈时,就会把本层绘制的图像“绘制”到上层或是Canvas上
最后最好加上  能让原始的背景色显示出来
paint.setXfermode(null);// 这样就没有了叠加模式 
canvas.restoreToCount(1);//因为让layer退栈 把本层绘制到上层 那么 上边这个 也是对应的叠加模式

即canvas为最下层即1 栈顺序如下图所示

这里写图片描述

疑问:

canvas.restoreToCount(1);//可以不用 按道理多图层应该是会用到!!!但是不知道为啥不用也好使!!!
如果有人懂的话 求告知

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值