在Android上运行流畅自定义动画的首选方式

时间:2014-11-03 23:37:21

标签: android multithreading animation android-asynctask background-process

我需要在Android应用中运行复杂的自定义动画。为此,我编写了一个需要重复调​​用的函数,并使用当前时间戳来计算屏幕上View元素的位置,颜色,阴影等。

我可以使用一大堆不同的方法来调用此函数:

在我目前的实现中,我只是通过runOnUIThread从一个单独的线程调用我的动画函数。虽然它有效,但它似乎不是一个好主意,因为它可能会使事件队列充满信息,而不是可以处理或者在屏幕刷新时需要消息......

我在几个小时后发布了similar question for iOS并且@IanMacDonald为我提供了一个惊人的答案,它允许在每次屏幕刷新之前调用我的功能一次,它可以制作出非常流畅的动画。有没有类似我在Android中可以做的事情,即每次屏幕即将刷新时都调用我的函数?

如果可能,我想使用尽可能向后兼容的方法,最好是API 7或更低版​​本......

1 个答案:

答案 0 :(得分:1)

我做了一些阅读,似乎目前首选的方法是使用Choreographer's postFrameCallback方法。不幸的是,Choreographer仅在API 16中添加,这对我的用例来说有点过于严格。

通过"递归"这是一种方法。 View.postDelayed调用(即Runnable将自行重新发出View.postDelayed),延迟时间为Display.getRefreshRate

import android.app.Activity;
import android.view.Display;
import android.view.View;

public abstract class DisplayRefreshTimer implements Runnable {

    public DisplayRefreshTimer(final View view) {
        Activity activity = (Activity) view.getContext();
        Display display = activity.getWindowManager().getDefaultDisplay();
        final int delay = (int) (1000 / display.getRefreshRate());
        view.postDelayed(new Runnable() {
            @Override
            public void run() {
                view.postDelayed(this, delay);
                DisplayRefreshTimer.this.run();
            }
        }, delay);
    }
}

要使用它,只需对其进行子类化,覆盖run()并实例化将其传递给当前视图:

new DisplayRefreshTimer(currentView) {
    @Override
    public void run() {
        // Do your magic here...
    }
};

如果你的目标是API 17+,你可以使用View.getDisplay而不是通过活动,但是你可能会像上面提到的那样关注Choreographer。

请不要让这个初步答案阻止您发布其他想法。如果有更好的解决方案仍然隐藏在某处,我不会感到惊讶。也许在OpenGL框架中?乍一看,我无法找到任何东西,但我也一直在寻找。