在Android上屏蔽可绘制/位图

在Android上屏蔽可绘制/位图,android,bitmap,mask,drawable,Android,Bitmap,Mask,Drawable,我目前正在寻找一种方法,使用黑白位图来屏蔽另一个位图或Android上可绘制的alpha通道。我很好奇做这件事的最好方法是什么。对于如何做到这一点,我当然有一些想法,但它们不是最优的 我需要能够应用一个新的遮罩到图像每隔一段时间(黑白位图将改变每隔几秒钟) 任何关于如何实现这一目标的反馈都将不胜感激。我不完全清楚您的目标,但我相信和的结合可能会奏效。BitmapDrawable将允许您将位图用作可绘制对象,然后您可以使用LayerDrawable将掩码分层到另一个可绘制对象上。使用API演示中的

我目前正在寻找一种方法,使用黑白位图来屏蔽另一个位图或Android上可绘制的alpha通道。我很好奇做这件事的最好方法是什么。对于如何做到这一点,我当然有一些想法,但它们不是最优的

我需要能够应用一个新的遮罩到图像每隔一段时间(黑白位图将改变每隔几秒钟)


任何关于如何实现这一目标的反馈都将不胜感激。

我不完全清楚您的目标,但我相信和的结合可能会奏效。BitmapDrawable将允许您将位图用作可绘制对象,然后您可以使用LayerDrawable将掩码分层到另一个可绘制对象上。

使用API演示中的Xfermodes示例,我能够使用应用于绘制对象的PorterDuffXfermode在画布上混合两个位图。这正是我所需要的。

我让它工作了,所以它是这样的

    // we first same the layer, rectF is the area of interest we plan on drawing
    // this will create an offscreen bitmap
    canvas.saveLayer(rectF, null, Canvas.MATRIX_SAVE_FLAG
            | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
            | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
            | Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    // draw our unmasked stuff
    super.draw(canvas);
    // We same a layer again but this time we pass a paint object to mask
    // the above layer
    maskPaint = new Paint()
    maskPaint.setColor(0xFFFFFFFF);
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

    canvas.saveLayer(rectF, maskPaint,
            Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
                    | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                    | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                    | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
    // we draw the mask which is black and white. In my case
    // I have a path, and I use a blurPaint which blurs the mask slightly
    // You can do anti aliasing or whatever you which. Just black & white
    canvas.drawPath(path, blurPaint);
    // We restore twice, this merges the results upward
    // as each saveLayer() allocates a new drawing bitmap
    canvas.restore();
    canvas.restore();
我做了一个可屏蔽的布局。 这是一个框架布局,您可以在其中指定xporterduffmode和掩码。
您可以在这里找到它:

我的解决方案接近@over\u optimistic的解决方案,少了一个saveLayer()调用。我使用了一个可绘制的遮罩而不是路径,在我的例子中,它是一个光盘

我将这些变量声明为字段(最好在onDraw方法之外分配内存):

为了更好地理解传输模式,我参考了。
那一页读起来很有趣。在那之后,使用同样的代码,你将能够获得比一个简单的掩码多得多的东西

我正在尝试使用遮罩位图的黑色部分将另一个位图/Drawable上对应像素的alpha通道设置为0。是否可以添加更多详细信息?如果覆盖onDraw方法,而不是
super.draw(画布)
应该有
super.onDraw(画布)
。否则,您将陷入层出不穷的循环,出现StackOverflow错误。我在自定义视图的
onDraw
中做了与上面相同的事情,但似乎
saveLayer
很昂贵,因此我为视图设置了一个硬件层(
view.setLayerType(layer\u TYPE\u hardware,paint)
)。更多信息:完美的解决方案。其他的有点太长了。我比公认的答案要好,我更喜欢可绘制的路径。如果你想要遮罩部分是透明的,这将不起作用。
private Paint maskingPaint = new Paint();
private Drawable mask = <insert your drawable here>
// Xfermode won't work if hardware accelerated
setLayerType(View.LAYER_TYPE_SOFTWARE, null);

// Using destination shape as a mask
// For a good explanation of PorterDuff transfer modes : http://ssp.impulsetrain.com/porterduff.html
maskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
maskingPaint.setAntiAlias(true);

// Position the mask
mask.setBounds(<insert your mask bounds here>);
@Override
protected synchronized void onDraw(Canvas canvas)
{
    // Draw the mask first, making it the PorterDuff destination
    mask.draw(canvas);

    // Save the layer with the masking paint, that will be applied on restore()
    // Using CLIP_TO_LAYER_SAVE_FLAG to avoid any overflow of the masked image outside the mask bounds.
    Rect bounds = mask.getBounds();
    canvas.saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, maskingPaint, 
            Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    // Draw the shape offscreen, making it the PorterDuff source
    super.onDraw(canvas);

    // Apply the source to the destination, using SRC_IN transfer mode
    canvas.restore();
}