我正在以编程方式生成一个大图像,该图像在某些区域具有纯白色填充,而在其他区域则完全透明。我希望能够用单色突出显示图像的一部分。我能想到的最简单的方法是在ImageView的顶部放置另一个View,并使它的背景变为纯色。然后,我想使用Porter Duff Xfer模式将视图的背景色乘到图像上。从数学上讲,这会将视图的颜色仅应用于白色填充区域,而其他区域将保持完全透明。
有没有办法做到这一点?我已经尝试过以下方法,方法是创建一个视图以使用设置了xfer模式的绘画进行绘制。
class FilterView : View {
private val paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.FILL
alpha = 0xFF
xfermode = PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)
}
var filterColor: Int
get() = paint.color
set(value) {
paint.color = value
invalidate()
}
constructor(context: Context) : this(context, null, 0)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
: this(context, attrs, defStyleAttr, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int)
: super(context, attrs, defStyleAttr, defStyleRes) {
val typedArray = context
.obtainStyledAttributes(attrs, R.styleable.FilterView, defStyleAttr, defStyleRes)
try {
paint.color = typedArray.getColor(R.styleable.FilterView_filterColor, Color.WHITE)
}
finally {
typedArray.recycle()
}
}
private val bounds = Rect()
override fun onDraw(canvas: Canvas) {
canvas.getClipBounds(bounds)
canvas.drawRect(bounds.left.toFloat(),
bounds.top.toFloat(),
bounds.right.toFloat(),
bounds.bottom.toFloat(),
paint)
}
}
当前使用这种方法,应用xfer模式会导致视图的颜色完全变为黑色,这使我相信Canvas可能不会从堆栈中的其他视图获得源颜色数据。
我还尝试在过滤器视图中使用以下内容:
...
private val layerPaint = Paint().apply {
alpha = 0xFF
colorFilter = null
xfermode = PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)
}
constructor(...):super(...) {
...
setLayerPaint(layerPaint)
setLayerType(LAYER_TYPE_SOFTWARE, layerPaint)
}
但这会导致整个叠加视图消失。