我想做的是
我正在尝试实现一个可以被屏蔽的视图。假设用户有这样的图像:

它被这样的自定义形状所掩盖:

由此产生的图像应该只让鞋擦通过,并使背景透明。
实现
我曾试图以这样的方式实施:
transparent
draw函数,使用DST_IN的xfermode (PorterDuffXfermode)在原始图像上绘制掩码。(见Android docs for PorterDuff.Mode)它工作得非常好,给了我这个图像(绿色像素表示透明):

虽然这很好,但我无法实现一个自定义的“绘图”功能,让用户绘制或擦除掩码。我只成功地做了一个或另一个,但不是同时做。这就是我现在所取得的成就:

请注意,擦除掩码的效果与预期相同,但试图扩展掩码并不有效,而是绘制白色像素(而不是让原始图像(鞋)擦过)。
这是我现在使用的代码:
override fun draw(baseCanvas: Canvas) {
super.draw(baseCanvas)
val image = imageBitmap
val mask = maskBitmap
val drawingBitmap = drawingBitmap
if (image != null && mask != null && drawingBitmap != null) {
run {
val canvas = Canvas(drawingBitmap)
// 1. Fill with white
canvas.drawColor(Color.WHITE)
// 2. Draw mask and only let non-transparent pixels through
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
canvas.drawBitmap(mask, 0f, 0f, paint)
// 3. Draw all lines point to point with white color and custom xfermode
paint.xfermode = null
paint.style = Paint.Style.STROKE
paint.color = Color.WHITE
paint.strokeWidth = penSize
paint.isDither = true
paint.strokeJoin = Paint.Join.ROUND
paint.strokeCap = Paint.Cap.ROUND
paint.pathEffect = CornerPathEffect(10f)
paint.isAntiAlias = true
lines.forEach { line ->
paint.xfermode = when (line.drawMode) {
DrawMode.ERASE -> PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
DrawMode.DRAW -> PorterDuffXfermode(PorterDuff.Mode.SRC)
}
val path = Path().also { path ->
val points = line.points
val range = points.size - 1
for (i in 1..range) {
path.moveTo(points[i - 1].x, points[i - 1].y)
path.lineTo(points[i].x, points[i].y)
}
}
canvas.drawPath(path, paint)
}
}
run {
val canvas = Canvas(image)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)
canvas.drawBitmap(drawingBitmap, 0f, 0f, paint)
}
}
}范围内的重要变量:
imageBitmap:bitmapmaskBitmap:--该位图包含白色以使原始形状发光,对于应该是transparentdrawingBitmap:的所有内容都是透明的--一个与imageBitmap大小相同的空位图,我只使用它绘制,然后将结果绘制到imageBitmap上(使用画布,请参见第二个run block)lines:,即我想要绘制的线条)。一条线由drawMode (绘制或擦除)和我跟踪的所有点的列表组成。奇怪的观察
现在让我困惑的是,当我在添加图像之前填充画布时:
run {
val canvas = Canvas(image)
canvas.drawColor(Color.BLACK) // <-- ADD THIS HERE
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)
canvas.drawBitmap(drawingBitmap, 0f, 0f, paint)
}看上去很正常:

同样的结果,如果我填充画布红色,它让红色的颜色发光,而不是黑色。为什么它适用于颜色,而不是原始位图?
如果在调试器中检查,它甚至看起来是正确的:

问题
这里有人知道为什么这不像我期望的那样起作用吗?我试着玩各种不同的PorterDuff模式,但没能使它顺利地工作。
任何帮助都很感激!
发布于 2021-09-08 09:27:26
好吧我让它起作用了。我不确定是否有更有效的方法来实现这一点,但我就是这样做的:
imageDrawingBitmap.
ImageView
imageDrawingBitmap的Bitmap,首先绘制掩码,然后在imageDrawingBitmapmaskDrawingBitmap来自步骤3)。在画布上用PorterDuff PorterDuff看来效果不错。
https://stackoverflow.com/questions/69091574
复制相似问题