【发布时间】:2015-12-28 11:45:52
【问题描述】:
我正在尝试使用SurfaceView 制作一个简单的秒表。它显示百分之一秒,因此它会尝试尽可能频繁地更新以保持流畅的动画。它在运行 4.0.3 的平板电脑和运行 4.0.4 的手机上运行良好,但是当我在 4.4.4 上尝试时,似乎有些撕裂,我无法解释。
底部的图像显示了应该发生的事情,并且在大多数情况下它是有效的。但是,每隔几秒钟就会出现一次闪烁。当我设法在正确的时间暂停时,我看到 一些 的数字被移到了右边。他们只会向右移动(上图)。这只发生了几分之一秒,刚好足以引起明显的闪烁。
请注意,数字使用一次计算的值(在onMeasure() 中)定位在画布上,并存储在类字段中。它们在初始化后不会改变。我通过记录onDraw() 内部的每个像素值来测试这一点。
在上图中,转置的是分钟值,但有时是其他数字。它们似乎总是在一组中被调换;分钟、秒或厘秒。
进一步:这只影响drawText()。我有这个秒表的更复杂版本,有很多路径、圆圈等。问题只发生在文本上。
我查看了关于 SO 和其他地方的几个问题和 cmets。这是我确定的:
我认为这不是缓冲区问题。行为似乎类似于 基于缓冲区的撕裂的描述,但在这种情况下,我不认为 问题可能是旧数据被发布到屏幕上,因为 数字从不在它们显示的位置绘制。
我在评论中读到它可能与 更新在
onDraw()之间多次调用的值 方法调用。我已尝试限制更新,但问题 持续存在。我还尝试绘制到临时位图并使用
canvas.drawBitmap()onDraw()函数,再次无济于事。
基本上,我想知道:
- 是什么导致了这个问题?
- 为什么它只在更高版本的 Android 中?
- 我该怎么办?
【问题讨论】:
-
听起来不像是“闪烁”,而是偶尔在错误的位置绘制文本。当您说您绘制临时位图“无济于事”时,这是否意味着您继续看到在错误位置呈现的分钟数字?它总是分钟数字吗?使用
screenrecord获取录音,然后逐帧浏览。当框架绘制不正确时,计数器是向前前进还是向后跳跃?覆盖onDraw()在 SurfaceView 上绘图是个坏主意;重命名函数,去掉“@Override”,并确认问题仍然存在。 -
我确实尝试将绘图放入自定义方法中,这解决了问题,但导致帧率大幅下降,所以我重新使用 onDraw。我会按照你的建议尝试录制。
-
如果您使用的是
onDraw(),那么当应用程序框架刷新 View UI 时,您将在 View 上绘图(就像自定义 View 一样)而不是 Surface。 View 与 Surface 重叠,因此您在两个重叠的图层上绘图。 Surface 的大小不必与 View 的大小相同,因此使用onMeasure()是不合适的(参见SurfaceHolder#setFixedSize())。您可能应该改用自定义视图:developer.android.com/training/custom-views/index.html -
有趣...我最初尝试使用自定义视图,但帧率从来没有高到足以使动画看起来流畅。
-
按速度递减顺序: (1) 使用 OpenGL 渲染到 SurfaceView Surface; (2) 使用 Canvas 渲染到硬件加速的自定义视图上; (3) 使用 Canvas 渲染到 SurfaceView Surface 上。并非所有 Canvas 操作都可以在所有版本的 Android 上在硬件中完成;见developer.android.com/guide/topics/graphics/hardware-accel.html。
标签: android android-canvas surfaceview