I am trying to draw an animation. To do so I have extended View and overridden the onDraw() method. What I would expect is that each time onDraw() is called the canvas would be in the state that I left it in and I could choose to clear it or just draw over parts of it (This is how it worked when I used a SurfaceView) but each time the canvas comes back already cleared. Is there a way that I can not have it cleared? Or maybe save the previous state into a Bitmap so I can just draw that Bitmap and then draw over top of it?
3 Answers
I'm not sure if there is a way or not. But for my custom views I either redraw everything each time onDraw() is called, or draw to a bitmap and then draw the bitmap to the canvas (like you suggested in your question).
Here is how i do it
class A extends View {
private Canvas canvas;
private Bitmap bitmap;
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (bitmap != null) {
bitmap .recycle();
}
canvas= new Canvas();
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
public void destroy() {
if (bitmap != null) {
bitmap.recycle();
}
}
public void onDraw(Canvas c) {
//draw onto the canvas if needed (maybe only the parts of animation that changed)
canvas.drawRect(0,0,10,10,paint);
//draw the bitmap to the real canvas c
c.drawBitmap(bitmap,
new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()),
new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()), null);
}
}

- 3,222
- 1
- 17
- 19
-
I figured this out just a little bit ago! Thanks for the input! – CaseyB Mar 11 '10 at 16:43
-
Drawing to buffer works fine, but this huge drawBitmap() method eats lots of FPS :( – Pavel Alexeev Aug 13 '11 at 20:00
-
It is a bottleneck for me right now - to draw fullscreen bitmap in onDraw each time to restore previous state hardly impacts FPS for high resolution devices (like Kindle 8.9 3rd gen with 2560x1600). Is there really no way to force canvas persist it's previous state? Deepening into OpenGL may probably solve performance issue, however it is not the way by the time. – vir us Feb 26 '14 at 21:32
you should have a look here to see the difference between basic view and surfaceView. A surfaceView has a dedicated layer for drawing, which I suppose keeps track of what you drew before. Now if you really want to do it on a basic View, you could try to put each item you draw in an array, like the exemple of itemized overlay for the mapview. It should work pretty much the same way

- 50,022
- 30
- 123
- 131
-
I saw that page. In fact that page lead me to use a SurfaceView initially, but then I found that the SurfaceView cannot have a transparent background. and I need this widget to be able to sit on top of other views. – CaseyB Mar 11 '10 at 08:07
-
-
In modern Android you can use a texture view if you want to go the OpenGL route. – Adam Jul 02 '14 at 07:55
Your expectations do not jib w/ reality :) The canvas will not be the way you left it, but it blank instead. You could create an ArrayList of objects to be drawn (canvas.drawCircle(), canvas.drawBitmap() etc.), then iterate though the ArrayList in the OnDraw(). I am new to graphics programming but I have used this on a small scale. Maybe there is a much better way.

- 879
- 9
- 13
-
It is if you create the canvas. That way you have total control over what is drawn to it. – CaseyB Mar 31 '10 at 21:05
-
Instead of an Arraylist: you can use the Picture class for recording drawing calls. – Jeremy List Jun 04 '13 at 07:27