Android View.onDraw() always has a clean Canvas

2019-01-08 17:48发布

问题:

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?

回答1:

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);
    }
}


回答2:

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



回答3:

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.