Xfermode 效果展示

遇到的问题
PorterDuff.Mode是两个图像共同绘制时图像颜色融合策略。
我们写代码时很容易:单独画一个圆,再单独画一个正方形,这个两个的交集只有两个图像重叠的部分。
xfermode只处理重叠的部分。
我们写代码时,我们需要创建两个同样大小的Bitmap, 一个里面绘制圆,一个里面绘制方形,然后再做融合,就会呈现出官网一样的效果。
官网地址
PorterDuff.Mode
源码如下:
class XfermodeView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val paint = Paint().also { it.isAntiAlias = true }
private val textPaint = TextPaint().also {
it.isAntiAlias = true
it.color = Color.BLACK
it.textSize = 30f
}
private val boundsList = ArrayList<RectF>()
private val bitmapCircles = ArrayList<Bitmap>()
private val bitmapSquares = ArrayList<Bitmap>()
private val porterDuffs = ArrayList<PorterDuffXfermode>()
private val length = PorterDuff.Mode.values().size
private val texts = ArrayList<String>()
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
val size = 3
val itemSize = width / size
var lineHeight: Float
var widthSize: Float
for (index in 0 until length) {
lineHeight = (index / size) * itemSize.toFloat()
widthSize = (index % size) * itemSize.toFloat()
boundsList.add(
RectF(
widthSize,
lineHeight,
itemSize.toFloat() + widthSize,
lineHeight + itemSize.toFloat()
)
)
}
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.ADD.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.CLEAR.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DARKEN.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DST.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DST_ATOP.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DST_IN.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DST_OUT.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.DST_OVER.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.LIGHTEN.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.MULTIPLY.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.OVERLAY.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SCREEN.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SRC.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SRC_IN.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SRC_OUT.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.SRC_OVER.also { texts.add(it.name) }))
porterDuffs.add(PorterDuffXfermode(PorterDuff.Mode.XOR.also { texts.add(it.name) }))
for (index in 0 until length) {
bitmapCircles.add(Bitmap.createBitmap(itemSize, itemSize, Bitmap.Config.ARGB_8888))
bitmapSquares.add(Bitmap.createBitmap(itemSize, itemSize, Bitmap.Config.ARGB_8888))
}
for (index in 0 until length) {
val canvas = Canvas()
canvas.setBitmap(bitmapCircles[index])
paint.color = Color.parseColor("#d81b60")
canvas.drawCircle(itemSize / 3f * 2, itemSize / 3f, itemSize / 3f, paint)
canvas.setBitmap(bitmapSquares[index])
paint.color = Color.parseColor("#2196f3")
canvas.drawRect(0f, itemSize / 3f, itemSize / 3f * 2f, itemSize.toFloat(), paint)
}
}
override fun onDraw(canvas: Canvas) {
for (index in 0 until length) {
val rectF = boundsList[index]
val layer = canvas.saveLayer(rectF, null)
canvas.drawBitmap(bitmapCircles[index], rectF.left, rectF.top, paint)
paint.xfermode = porterDuffs[index]
canvas.drawBitmap(bitmapSquares[index], rectF.left, rectF.top, paint)
paint.xfermode = null
canvas.restoreToCount(layer)
canvas.drawText(texts[index], rectF.left + 20, rectF.top + 100, textPaint)
}
}
}