The method below works, but it unfortunately, this method involves creating a bitmap the size of the entire screen - not just the area that is drawn to. If I use this to draw UI elements, it is redrawn for each UI element. Can this be done more efficiently?
@Override
protected void onDraw(Canvas canvas) {
//TODO: Reduce the burden from multiple drawing
Bitmap bitmap=Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888);
Canvas offscreen=new Canvas(bitmap);
super.onDraw(offscreen);
//Then draw onscreen
Paint p=new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
canvas.drawBitmap(bitmap, 0, 0, p);
}
The following code will be much more efficient.
public class MyView extends TextView{
private Canvas offscreen;
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
//We want the superclass to draw directly to the offscreen canvas so that we don't get an infinitely deep recursive call
if(canvas==offscreen){
super.onDraw(offscreen);
}
else{
//Our offscreen image uses the dimensions of the view rather than the canvas
Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
offscreen=new Canvas(bitmap);
super.draw(offscreen);
//Create paint to draw effect
Paint p=new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
//Draw on the canvas. Fortunately, this class uses relative coordinates so that we don't have to worry about where this View is actually positioned.
canvas.drawBitmap(bitmap, 0, 0, p);
}
}
}
Have you tried changing the size of the bitmap you create, to be only equal to the clip bounds rather than the entire size of the given canvas? I don't know if this is the case with all Views, but I found that the onDraw method for some Views is given a canvas as big as the screen, regardless of the actual size of the content. It then clips the canvas, restricting it to the top left corner only, draws there and then translates that part to somewhere else on the screen when it's actually ready to display the whole layout. In other words, despite it having a canvas the size of the whole screen, it only actually uses a small piece of it. So what you could try doing is instead of using
Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), ...)
you could try
Rect rect = canvas.getClipBounds();
int width = rect.width();
int height = rect.height();
Bitmap bitmap = Bitmap.createBitmap(width, height, ...);
That way you reduce the overhead of working with a much larger bitmap than necessary. Note: I haven't actually tried doing this so it might not work, but it's worth trying.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With