PorterDuffXfermode 正确使用方式(详解)

来源:互联网 发布:巨人网络 校招 编辑:程序博客网 时间:2024/04/30 10:41

这里写图片描述

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

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 0
原创粉丝点击