There isn't a direct API in the framework that allows you to trace a solid image mask and generate a Path
that you can use to do clipping. If you can access the mask contents as SVG, you might be able to use the path tracing techniques Romain Guy describes here:
http://www.curious-creature.org/2013/12/21/android-recipe-4-path-tracing/
While this isn't my favorite technique, the best option I've seen is basically a combination of the items you've already described. We need to create an off-screen buffer (via a Canvas+Bitmap) into which the view contents can be rendered, and then use the transfer mode technique to apply the result onto the Canvas attached to the window. I have not tried this with a ViewGroup
in dispatch, but it should work. The following (untested) code would be a starting point:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
//Create an area to use for content rendering
mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mCanvasBitmap);
mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
//Render contents into our buffer
super.dispatchDraw(mCanvas);
//Render the mask, clipping with a PorterDuffXfermode
paint.setXfermode(mXfermode);
mCanvas.drawBitmap(mMask, 0, 0, paint);
//Clear state and transfer result
paint.setXfermode(null);
canvas.drawBitmap(mCanvasBitmap, 0, 0, paint);
}
One drawback to this approach is memory; with a sufficiently large view you must allocate an extra block equal to the size of the view container. We can minimize this impact by doing it once and reusing the buffer.