SurfaceView drawText闪烁

时间:2015-09-30 15:42:36

标签: android android-canvas surfaceview

我正在尝试使用SurfaceView制作一个简单的秒表。它显示百分之一秒,因此它会尽可能频繁地更新以保持平滑的动画。它在我运行4.0.3的平板电脑和运行4.0.4的手机上运行得非常好,但是当我在4.4.4上尝试它时,似乎有一些我无法解释的撕裂。

This is an emulator running 4.4.4, but the problem happens on a hardware device as well.

底部图像显示了应该发生的事情,并且大多数情况下都有效。但是,每隔几秒就有一次闪烁。当我设法在正确的时间暂停时,我看到一些的数字被转换到右边。他们只向右移动(顶部图像)。这种情况只发生在几分之一秒内,只要足够长就会引起明显的闪烁。

请注意,数字位于画布上,使用计算一次的值(在onMeasure()中)并存储在类字段中。它们在初始化后不会改变。我通过记录每个onDraw()内的像素值来测试它。

在上图中,它是转置的分钟值,但有时它是其他数字。它们似乎总是被转换成一组;分钟,秒或两个厘秒。

此外:这只影响drawText()我有更多复杂版本的秒表,有很多路径,圆圈等。问题只发生在文字上。

我查看了有关SO和其他地方的几个问题和评论。这就是我所确定的:

  • 我认为这不是缓冲问题。这种行为似乎与此类似 基于缓冲区的撕裂的描述,但在这种情况下我不会想到 问题可能是旧数据被发布到屏幕上,因为 数字从不在显示的位置绘制。

  • 我在评论中读到它可能与该功能有关 更新onDraw()之间多次调用的值 方法调用。我试过限制更新,但问题 仍然存在。

  • 我还尝试绘制到临时位图并使用canvas.drawBitmap() onDraw()功能再次无济于事。

基本上,我想知道:

  • 导致此问题的原因是什么?
  • 为什么只能在更高版本的Android中使用?
  • 我该怎么办?

1 个答案:

答案 0 :(得分:1)

在阅读@ fadden的评论后,我能够更有效地搜索。

似乎我的错误是试图在动画线程中调用onDraw()。当我将这一个电话改为postInvalidate()时,它立即解决了问题。简而言之,动画循环的内部如下所示:

holder = view.getHolder();
canvas = holder.lockCanvas();
if (canvas != null) {
    synchronized (holder) {
        if (view != null) {
            view.DEBUG_THREADCALLS++;
            // NOT view.onDraw(), but:
            view.postInvalidate();
        }
    }
}

根据我的理解,对onDraw()的调用会导致问题,因为它会导致应用程序同时绘制ViewSurface

我猜这个问题只出现在更现代的Android版本中的原因可能是因为较新的设备具有更高的刷新率,因此问题更加明显。我注意到该解决方案还显着提高了我最老的设备的帧速率,这可能是因为它不能同时如此努力地吸引到两个地方。

<强>更新

根据以下极其有用的评论的进一步建议,我完全删除了SurfaceView,现在使用单独的动画线程绘制自定义视图。即使在较旧的设备上,结果也是令人难以置信的流畅动画,远远优于SurfaceView!所以对于其他试图用SurfaceView进行动画制作的人,我说:除非你有充分的理由,否则不要!