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

主要多亏了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()
           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深入试验)这篇文章,向英勇的排雷者致敬😂