说起Xfermode,网上随便一搜就有很多解释。诸多解释中都会包含这张图,看的确实明白,用起来的时候才知到有多坑。

Xfermode对应效果图.png

主要多亏了PorterDuffXferMode不正确的真正原因PorterDuffXferMode深入试验)这篇文章,才不至于摔死在坑中。

可以解决的问题

如果你在使用XferMode的过程中遇到了 参数设置无效,不显示图案,显示图案不正确,显示图案有时候正确有时候不正确,显示图案和参数不符…等一系列花里胡哨的问题时候,不妨看看本文。

结论

先说结论,PorterDuffXferMode的正常使用需满足以下条件:

  • 关闭硬件加速
  • 背景色为透明
  • 必须使用bitmap绘制!!(这里解释了为什么有的同学用drawRect,drwaCiclebug一片的问题😖
  • 上图中xferMode的所有效果都是在两个bitmap重合的区域发生,所以一般情况下,两个bitmap的位置和大小尽量保持一致。

测试代码

若是信不过这个结论,在下有代码一份可供参考使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class XFerModeView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr){
private val paint:Paint = Paint()

//修改此处xfemode的值,即可看到相应效果
private val xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)

private val mSrcBitmap: Bitmap = Bitmap.createBitmap(800,800, Bitmap.Config.ARGB_8888)
private val mSrcCanvas = Canvas(mSrcBitmap);
private val mDstBitmap: Bitmap = Bitmap.createBitmap(800,800, Bitmap.Config.ARGB_8888)
private val mDstCanvas = Canvas(mDstBitmap)

init {
paint.apply {
color = Color.YELLOW
style = Paint.Style.FILL
}
setLayerType(View.LAYER_TYPE_SOFTWARE, null)//关闭硬件加速
mDstCanvas.drawCircle(200f,200f,200f,paint)
paint.color = Color.BLUE
mSrcCanvas.drawRect(200f,200f,500f,500f,paint)
}

override fun onDraw(canvas: Canvas) {
canvas.drawBitmap(mDstBitmap,0f,0f,paint)
paint.xfermode = xfermode
canvas.drawBitmap(mSrcBitmap,0f,0f,paint)
}

}

任意修改xfermode的值,可查看效果,所显示于示例一致。

细节

具体的踩坑细节可以看PorterDuffXferMode不正确的真正原因PorterDuffXferMode深入试验)这篇文章,向英勇的排雷者致敬😂