15

我有一个填满整个屏幕的自定义视图。(钢琴键盘)当用户触摸键时,它会invalidate()被调用,整个键盘被重绘以显示触摸键的新状态。

目前视图非常简单,但我计划添加更多漂亮的图形。由于整个键盘是动态渲染的,因此重绘整个键盘的成本会更高。

所以我想,让我们看看部分重绘。现在我invalidate(Rect dirty)用正确的脏区打电话。onDraw(Canvas canvas)如果我确实想要部分重绘,我将我的方法设置为仅在脏区中绘制键。这导致这些键被绘制,但键盘的其余部分完全是黑色的/根本没有绘制。

我期望调用invalidate(Rect dirty)会“缓存”当前canvas,并且只“允许”在脏区域中绘制,我错了吗?

有什么办法可以实现我想要的吗?(一种“缓存”画布并只重绘脏区的方法?”

4

2 回答 2

19

当前不错的解决方法是将整个画布手动缓存到位图:

 private void onDraw(Canvas canvas)
 {
     if (!initialDrawingIsPerformed)
     {
          this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
            Config.ARGB_8888); //Change to lower bitmap config if possible.
          Canvas cacheCanvas = new Canvas(this.cachedBitmap);
          doInitialDrawing(cacheCanvas);
          canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
          initialDrawingIsPerformed = true;
     }
     else
     {
          canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
          doPartialRedraws(canvas);
     }
 }

当然,您需要存储有关自己重绘什么的信息,最好不要Paint每次都使用新的,但这是细节。

另请注意:位图对您的应用程序的内存使用非常重要。当我缓存一个与滚动条一起使用的视图时,我遇到了崩溃,它是设备高度的 5 倍,因为它使用了 > 10MB 的内存!

于 2010-06-01T12:09:00.483 回答
5

为了补充 Peterdk 的答案,您可以将操作保存在图片而不是位图中。

  • 位图将保存所有像素,就像他说的那样可能会占用大量内存。
  • Picture 将保存调用,如 drawRect、drawLine 等。

这取决于您的应用程序中真正繁重的内容:大量绘制操作,一些绘制操作但受繁重计算控制,大量空白/未使用空间(首选图片)等...

于 2011-05-06T09:51:12.627 回答