ScrollView 优化技巧

7
我有一个包含自定义视图的滚动视图。自定义视图比屏幕区域大,可以正确绘制。
然而,当滚动时,滚动视图 tends to call onDraw() 非常频繁,我无法使其平滑。
我使用 ScrollView.getDrawingRect() 计算屏幕上可见部分,并只绘制它,但它仍然返回整个视口(因此优化为不绘制屏幕外区域),而不是上一个位置和当前位置之间的增量。理想情况下,我只想绘制增量,而不是整个可见窗口。
如果有人能指导我如何使用绘图缓存,并且是否有助于优化滚动,我很乐意实现它,或者任何其他可能的解决方案都将不胜感激。
3个回答

5
当内容滚动时,整个视口需要重新绘制,因为所有内容都已经移动。我认为没有必要优化ScrollView - 如果滚动缓慢,则是您自定义视图的绘制方法太慢了。
尽量避免在绘制方法中创建对象,这通常是绘图性能不佳的主要原因。
编辑:此外,ScrollView可以快速地将仍然绘制在屏幕上的旧内容向上或向下传送,并仅请求重新绘制屏幕上的“新”部分。(仅适用于不透明视图)。

有更好的解决方案,我可以通过将视图绘制到位图中,然后在onDraw中绘制该位图而不是重新计算视图来实现自己的缓存。Android视图缓存应该能够做类似的事情,并且文档也暗示了这一点,但我从未看到过清晰地解释视图缓存的东西。 - HaMMeReD
你看过http://groups.google.com/group/android-developers/browse_thread/thread/224457b8cb4e039c?pli=1吗?但我同意,绘图缓存主题没有得到很好的讨论。 - Joseph Earl
目前我只实现了位图路线。在我的onDraw中,我会检查是否有缓存位图,如果存在,则创建与视图大小相同的位图,然后使用指向位图的画布调用我的旧onDraw。然后在常规onDraw中,它只是绘制位图。这是一种内存/性能权衡,但我在这里可以接受,因为这些视图不应该变得太大。如果无法分配缓存,则可以回退到直接绘制到视图。 - HaMMeReD

2
我遇到了同样的问题。我通过使用函数setDrawingCacheEnabled(true)解决了它。启用此设置后,您的画布视图将被缓存为位图,因此每次调用onDraw()时,您无需调用画布绘制方法。
在自定义视图的构造函数中,您需要像这样设置:
public CustomView(Context context) {
    setDrawingCacheEnabled(true);
    drawnFlag = false;
}

在你的onDraw方法中,你需要类似以下的内容:
public void onDraw(Canvas canvas) {
    if (! drawnFlag) {
        canvas.drawPath(...);
        canvas.drawPath(...);
        drawnFlag = true;
    }
}

现在,在此自定义视图上滑动应该很流畅,因为我们只调用绘制方法一次。

1
我不知道为什么没有人点赞你的答案。它是有效的!@Andree - zbz.lvlv

-1
据我所知,ScrollView 在 onDraw 中为画布设置了适当的剪辑矩形,因此您只需要绘制该矩形内部的内容。 您还可以根据剪辑矩形的大小实现缓存位图。

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