赞
踩
"setXfermode"这个方法能够做什么?大多数情况下我们知道这个就行。对于Android开发中碰到最多的是实现圆形图片显示或是圆角图片,而"setXfermode"的使用就能够实现我们想要的图片效果。
Xfermode 指的是你要绘制的内容和Canvas的目标位置的内容应该怎样结合计算出最终的颜色。通俗来讲就是要你以绘制的内容作为源图像,以 View 中已有的内容作为目标图像,选取一个PorterDuff.Mode 作为绘制内容的颜色处理方案。就像这样:
Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
...
canvas.drawBitmap(rectBitmap, 0, 0, paint); // 画方
paint.setXfermode(xfermode); // 设置 Xfermode
canvas.drawBitmap(circleBitmap, 0, 0, paint); // 画圆
paint.setXfermode(null); // 用完及时清除 Xfermode
下面是PorterDuff.Mode所有的效果图:
PorterDuff.Mode 在Paint一共有三处API,它们的工作原理都是混合计算,只是用途不一样:
API | 用途 |
ComposeShader | 混合两个Shader |
PoterDuffColorFilter | 增加一个单色的ColorFilter |
Xfermode | 设置绘制内容和View中已有内容的混合计算方式 |
Xfermode 使用是很简单的,不过还是有两点需要注意:
实质上,上面这段例子代码,如果直接执行的话是不会绘制出图中效果的。
按照逻辑我们会认为,在第二步画圆的时候,跟它共同计算的是第一步绘制的方形。但实际上,却是整个 View
的显示区域都在画圆的时候参与计算,并且 View
自身的底色并不是默认的透明色,而且是遵循一种迷之逻辑,导致不仅绘制的是整个圆的范围,而且在范围之外都变成了黑色。
要想使用 setXfermode() 正常绘制,必须使用离屏缓存 (Off-screen Buffer) 把内容绘制在额外的层上,再把绘制好的内容贴回 View 中。
使用离屏缓冲有两种方式:
saveLayer() 可以做短时的离屏缓冲。使用方法很简单,在绘制代码的前后各加一行代码,在绘制之前保存,绘制之后恢复:
int saved = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(rectBitmap, 0, 0, paint); // 画方
paint.setXfermode(xfermode); // 设置 Xfermode
canvas.drawBitmap(circleBitmap, 0, 0, paint); // 画圆
paint.setXfermode(null); // 用完及时清除 Xfermodecanvas.restoreToCount(saved);
View.setLayerType() 是直接把整个View都绘制在离屏缓冲中,
setLayerType(LAYER_TYPE_HARDWARE) 是使用GPU来缓冲,
setLayerType(LAYER_TYPE_SOFTWARE) 是直接用一个 Bitmap 来缓冲。
如果没有特殊需求,可以选用第一种方法 Canvas.saverLayer() 来设置离屏缓冲,以此来获得更高的性能。
使用 Xfermode 来绘制的内容,除了注意使用离屏缓冲,还应该注意控制它的透明区域不要太小,要让它足够覆盖到要和它结合绘制的内容,否则得到的结果很可能不是你想要的。我从网上找了张图来说明一下:
如图所示,由于透明区域过小而覆盖不到的地方,将不会受到 Xfermode 的影响。
好了,这篇文章到这里就结束了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。