Android Canvas 下动画形状的最佳实践

Best practices for animating shapes under Android Canvas

我有一个自定义视图,它绘制了几个圆圈和大约 10 个不断更新(旋转和大小变化)的拱门。我正在尝试为整个过程制作动画,但在 Canvas 下我找不到任何好的做法(我知道基础知识 - 使用 dp 而不是 px 等等),但我不知道热正确地做动画部分。

现在我正在遍历我的所有对象,执行一些计算以确定未来的位置并绘制它们,但它看起来很不稳定。这是我目前正在做的事情:

@Override
protected void onDraw(Canvas canvas) {
    for(Arch arch : arches) {
        arch.update();
        canvas.drawArc(arch.getRect(), -arch.getCurrentRotation(), arch.getSweepAngle(), true, paint);
    }

    //logo.draw(canvas);

    canvas.drawCircle(width / 2, height / 2, circle_size, paint_opaque);

    logo.draw(canvas);

    int textX = (int) (width / 2);
    int textY = (int) ((height / 2) - ((paint_text.descent() + paint_text.ascent()) / 2));

    canvas.drawText(text, textX, textY, paint_text);
    invalidate();
}

您的代码几乎没有错误。

  1. 您不应在自定义 ViewsonDraw 中执行任何 繁重的 操作。这是 android 开发的一个非常重要的原则!理想情况下,您应该只在 onDraw 方法中绘制。有时你需要根据 Canvas 计算一些东西,但你应该将这类操作限制在最低限度。您可以在其他地方(不在 onDraw 中)预先分配和计算的所有内容,都应该从您的 onDraw 中提取。在你的情况下 arch.update() (我假设计算动画的下一个 "frame" )并且你的 textXtextY 的计算应该移到其他地方。

  2. invalidate() 基本上意味着您请求重绘您的 View。当 View 被重绘时,它的 onDraw 将被调用。这就是为什么您真的不应该在 onDraw 中调用 invalidate()!如果每个 onDraw 请求另一个 onDraw,就会导致一种无限循环的发生。

  3. 如果您正在尝试实现帧动画,您应该在一个单独的线程中计算所有与帧相关的参数,该线程会在更新之间等待一段时间,并会调用 invalidate()在每一个之后。