androidviewgroupxfermode

Custom ViewGroup with Circular child


I'd like to implement custom ViewGroup which is displaying single View inside. The tricky part is that the child view have to be crop into circle shape and it have to be drawn fast.

What is the best way to implement this behavior?

My current implementation looks like this:

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    child.setDrawingCacheEnabled(true);
    child.buildDrawingCache();
    child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    canvas.drawBitmap(getCroppedBitmap(child.getDrawingCache()), outerWidth, outerWidth, new Paint());
    child.setLayerType(View.LAYER_TYPE_NONE, null);
    return true;
}

public Bitmap getCroppedBitmap(Bitmap bitmap) {
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
            bitmap.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    childPaint.setXfermode(null);
    canvas.drawARGB(0, 0, 0, 0);
    canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
            bitmap.getWidth() / 2, childPaint);
    childPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(bitmap, mBoundsI, mBoundsI, childPaint);
    return output;
}

(Every time new Canvas and Bitmap is created, and drawing cache is enabled)


Solution

  • probably the fastest way of achieving that is to let the views draw directly on canvas (avoiding the buffer and bitmap creation).

    For that you should specify on the canvas a clip path and with a Path that is set to an appropriate circle.

    Then the Canvas will not draw anything that is draw outside it's clipping path

    ps.: remember to use the appropriate REPLACE Region on subsequent calls on the clipPath