我目前正在尋找一種方法來使用黑白位圖來屏蔽Android上另一個位圖或Drawable的Alpha通道。我很好奇最好的方式是做什麼。對於如何做到這一點,我當然有一些想法,但它們並不是最優的。屏蔽Android上的Drawable/Bitmap
我需要能夠每隔一段時間對圖像應用一個新的遮罩(黑白位圖每隔幾秒就會改變一次)。
任何有關如何實現這一目標的反饋將不勝感激。
我目前正在尋找一種方法來使用黑白位圖來屏蔽Android上另一個位圖或Drawable的Alpha通道。我很好奇最好的方式是做什麼。對於如何做到這一點,我當然有一些想法,但它們並不是最優的。屏蔽Android上的Drawable/Bitmap
我需要能夠每隔一段時間對圖像應用一個新的遮罩(黑白位圖每隔幾秒就會改變一次)。
任何有關如何實現這一目標的反饋將不勝感激。
我得到它的工作,所以它是這樣的
// 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();
如果重寫onDraw方法,而不是'super.draw(canvas)'應該有'super.onDraw(canvas)'。否則,最終會出現StackOverflow錯誤的無限循環。 – Speedy 2013-04-05 08:21:42
我在自定義視圖的'onDraw'中做了與上面相同的事情,但是看起來'saveLayer'很昂貴,所以我沒有爲我的視圖設置一個硬件層('View.setLayerType(LAYER_TYPE_HARDWARE,paint) ')。更多信息:http://stackoverflow.com/a/33483016/4747587 – Henry 2015-11-02 17:12:25
我並不完全清楚你要做什麼,但我相信BitmapDrawable
和LayerDrawable
的組合可能會起作用。 BitmapDrawable將允許您使用您的位圖作爲Drawables,然後您可以使用LayerDrawable將遮罩層疊到另一個Drawable上。
我會檢查出來,謝謝。 – 2010-04-12 19:49:52
在API Demo中使用Xfermodes示例我能夠使用應用於Paint對象的PorterDuffXfermode在畫布上混合兩個位圖。這工作正是我需要它。
你可以添加更多的細節? – Casebash 2010-04-29 02:25:30
我做了一個屏蔽佈局。 這是一個框架佈局,您可以在其中指定xporterduffmode和掩碼。 你可以在這裏找到它:https://github.com/christophesmet/android_maskable_layout
我的解決方案接近@ over_optimistic的解決方案,少一個saveLayer()調用。我使用Drawable mask而不是路徑,在我的情況下它是一張光盤。
我宣佈這些變量作爲字段(這是很好的做法的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();
}
爲了更好地理解o f傳輸模式,我提到http://ssp.impulsetrain.com/porterduff.html。 該頁面非常有趣。之後,使用相同類型的代碼,您可以獲得比單純的面具更多的功能!
完美的解決方案。其他人有點太長了。 – Jona 2015-02-17 00:46:42
國際海事組織比接受的答案更好,我更喜歡在路徑上繪製 – 2017-03-03 08:36:44
我試圖使用掩碼位圖的黑色部分來設置其他位圖上的相應像素的Alpha通道/ Drawable爲0. – 2010-04-12 19:52:21