I have an ImageView
subclass that I use to draw images with rounded corners. The code is based on this answer, and is as follows:
public class ImageViewRoundedCorners extends ImageView {
...
@Override
protected void onDraw(Canvas canvas) {
Bitmap scaledBitmap = Bitmap.createBitmap(getMeasuredWidth(),
getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas scaledCanvas = new Canvas(scaledBitmap);
super.onDraw(scaledCanvas);
drawRoundedCornerBitmap(canvas, scaledBitmap,
getMeasuredWidth(), getMeasuredHeight());
scaledBitmap.recycle();
}
protected void drawRoundedCornerBitmap(Canvas outputCanvas, Bitmap input, int w, int h) {
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
mPaint.reset();
mPaint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mClipPath, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(input, 0, 0, mPaint);
outputCanvas.drawBitmap(output, 0, 0, null);
}
}
With this code, the image is drawn with properly rounded corners. To avoid the allocations on the first two lines of drawRoundedCornerBitmap
, I want to draw directly to outputCanvas
, which is the canvas originally passed to onDraw
. The new implementation looks like this:
protected void drawRoundedCornerBitmap(...) {
mPaint.reset();
mPaint.setAntiAlias(true);
outputCanvas.drawARGB(0, 0, 0, 0);
mPaint.setStyle(Paint.Style.FILL);
outputCanvas.drawPath(mClipPath, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
outputCanvas.drawBitmap(input, 0, 0, mPaint);
}
For some reason, this code seems to ignore the Porter-Duff mode, and instead just draws the image with normal (non-rounded) corners. Why is this the case? What is it about drawing to an intermediate Bitmap
that makes the original code work?