说起Xfermode,网上随便一搜就有很多解释。诸多解释中都会包含这张图,看的确实明白,用起来的时候才知到有多坑。
主要多亏了PorterDuffXferMode不正确的真正原因PorterDuffXferMode深入试验)这篇文章,才不至于摔死在坑中。
可以解决的问题
如果你在使用XferMode
的过程中遇到了 参数设置无效,不显示图案,显示图案不正确,显示图案有时候正确有时候不正确,显示图案和参数不符…等一系列花里胡哨的问题时候,不妨看看本文。
结论
先说结论,PorterDuffXferMode的正常使用需满足以下条件:
- 关闭硬件加速
- 背景色为透明
- 必须使用bitmap绘制!!(这里解释了为什么有的同学用
drawRect
,drwaCicle
bug一片的问题😖
- 上图中
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深入试验)这篇文章,向英勇的排雷者致敬😂