我目前正在寻找一种方法来使用黑白位图来掩盖另一个位图的alpha通道或Android上的Drawable。我很好奇最好的办法是什么。我当然对如何做到这一点有一些想法,但它们并不是最佳的。
我需要能够经常对图像应用新的遮罩(黑白位图每隔几秒就会改变一次)。
非常感谢任何有关如何实现这一目标的反馈。
答案 0 :(得分:6)
我的解决方案接近@ over_optimistic的解决方案,少了一个saveLayer()调用。我使用Drawable蒙版而不是路径,在我的例子中它是一张光盘。
我将这些变量声明为字段(在onDraw方法之外分配内存是一种很好的做法):
private Paint maskingPaint = new Paint();
private Drawable mask = <insert your drawable here>
然后,在onDraw()之外的某处,设置对象:
// 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>);
最后,onDraw()方法应用了掩码:
@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();
}
为了更好地理解传输模式,我提到了http://ssp.impulsetrain.com/porterduff.html。 该页面非常有趣。在那之后,使用相同类型的代码,您将能够获得比简单面具更多的效果!
答案 1 :(得分:4)
我做了一个可屏蔽的布局。 它是一个framelayout,您可以在其中指定xporterduffmode和掩码。 您可以在此处找到它:https://github.com/christophesmet/android_maskable_layout
答案 2 :(得分:3)
我得到了它,所以它就是这样的
// 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();
答案 3 :(得分:2)
我对你的目标并不完全清楚,但我认为BitmapDrawable
和LayerDrawable
的组合可能有用。 BitmapDrawable允许您将Bitmaps用作Drawables,然后您可以使用LayerDrawable将遮罩层叠在另一个Drawable之上。
答案 4 :(得分:1)
使用API Demo中的Xfermodes示例,我可以使用应用于Paint对象的PorterDuffXfermode将两个位图混合在画布上。这完全符合我的需要。