Мое решение близко к решению @ 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.
Эту страницу довольно интересно читать. После этого с тем же типом кода вы сможете получить гораздо больше, чем простая маска!