Android中的View.onDraw()始终具有清洁的画布。

19

我正在尝试绘制动画。为此,我扩展了View并覆盖了onDraw()方法。我期望的是每次调用onDraw()时,画布都处于我离开它的状态,我可以选择清除它或只是在其上绘制一部分内容(当我使用SurfaceView时它是这样工作的),但每次画布都已经被清除了。有没有办法让它不被清除?或者可以将先前的状态保存到位图中,这样我就可以仅绘制该位图然后在其上绘制其他东西?

3个回答

28

我不确定是否有方法可以实现。但是对于我的自定义视图,我要么在每次调用onDraw()时重新绘制所有内容,要么绘制到位图上,然后将位图绘制到画布上(就像您在问题中建议的那样)。

这是我的做法

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

我刚刚弄清楚这个问题了!感谢您的帮助! - CaseyB
绘制到缓冲区没问题,但是这个庞大的drawBitmap()方法消耗了很多帧率 :( - Pavel Alexeev
目前对我来说是一个瓶颈 - 在onDraw中每次绘制全屏位图以恢复先前状态,对于高分辨率设备(如Kindle 8.9第三代,分辨率为2560x1600)几乎没有影响FPS。真的没有办法强制画布保持其先前的状态吗?深入了解OpenGL可能会解决性能问题,但现在还不是这样做的时候。 - vir us

1

你应该在这里看一下基本视图和SurfaceView之间的区别。SurfaceView有一个专门的绘制层,我想它会跟踪你之前绘制的内容。现在,如果你真的想在基本视图上实现它,你可以尝试将每个绘制的项目放入一个数组中,就像地图视图的分项覆盖物示例一样。它应该工作方式基本相同。


我看到了那个页面。实际上,那个页面让我最初使用SurfaceView,但后来我发现SurfaceView不能有透明的背景,而我需要这个小部件能够放置在其他视图的顶部。 - CaseyB
然后尝试使用可绘制数组? - Sephy
在现代的Android中,如果你想使用OpenGL,可以使用纹理视图。 - Adam

0
你的期望与现实不符 :) 画布不会像你离开时那样,而是变成空白。你可以创建一个对象数组列表来绘制(canvas.drawCircle(), canvas.drawBitmap() 等),然后在 OnDraw() 中迭代整个数组列表。我对图形编程还很陌生,但我已经在小范围内使用过这种方法。也许有更好的方法。

如果您创建画布,那么您就可以完全控制绘制到画布上的内容。 - CaseyB
你可以使用Picture类来记录绘图调用,而不是使用ArrayList。 - Jeremy List

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接