当前位置:   article > 正文

自定义View——setXfermode

setxfermode

setXfermode

"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注意事项

Xfermode 使用是很简单的,不过还是有两点需要注意:

1.使用离屏缓冲(Off-screen Buffer)

实质上,上面这段例子代码,如果直接执行的话是不会绘制出图中效果的。

按照逻辑我们会认为,在第二步画圆的时候,跟它共同计算的是第一步绘制的方形。但实际上,却是整个 View 的显示区域都在画圆的时候参与计算,并且 View 自身的底色并不是默认的透明色,而且是遵循一种迷之逻辑,导致不仅绘制的是整个圆的范围,而且在范围之外都变成了黑色。

要想使用 setXfermode() 正常绘制,必须使用离屏缓存 (Off-screen Buffer) 把内容绘制在额外的层上,再把绘制好的内容贴回 View 中。

使用离屏缓冲有两种方式:

  • Canvas.saverLayer()

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);                                 // 用完及时清除 Xfermode

canvas.restoreToCount(saved);

  •  View.setLayerType()

View.setLayerType() 是直接把整个View都绘制在离屏缓冲中,

setLayerType(LAYER_TYPE_HARDWARE) 是使用GPU来缓冲,

setLayerType(LAYER_TYPE_SOFTWARE) 是直接用一个 Bitmap 来缓冲。

如果没有特殊需求,可以选用第一种方法 Canvas.saverLayer() 来设置离屏缓冲,以此来获得更高的性能。

2.控制好透明区域

使用 Xfermode 来绘制的内容,除了注意使用离屏缓冲,还应该注意控制它的透明区域不要太小,要让它足够覆盖到要和它结合绘制的内容,否则得到的结果很可能不是你想要的。我从网上找了张图来说明一下:

 如图所示,由于透明区域过小而覆盖不到的地方,将不会受到 Xfermode 的影响。

好了,这篇文章到这里就结束了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/332694
推荐阅读
相关标签
  

闽ICP备14008679号