8

我从头开始创建了一个自定义视图。扩展View和覆盖onDraw()。当在动画视图中下降时,我使用偏移量生成自定义动画。例如。

while(!isOnTop){
mOffset++;

//draw the component a a it higher using the offset

if(position == 0)
isOnTop==true;
invalidate();

}

我的想法是我的框架来自无效它自己。问题是该视图的失效可以通过在同一屏幕上滚动列表视图来实现。

这种“共享失效()”会导致我的动画滞后。那么有没有办法摆脱这种滞后?

您对在该共享环境中执行动画还有其他建议吗?使用计算偏移量的单独线程创建动画还需要强制调用 invalidation() 来显示动画(如果我错了,请纠正我)。

是在例如 10 个无效请求中执行动画的唯一解决方案吗?它会缓解延迟,但我认为我可以使用不同的方法。

4

2 回答 2

22

“什么是最好的”当然在很大程度上取决于你想要做什么。你还没有说你想要完成什么,所以我们只能猜测什么可能最适合你。

这里有一些简单的事情:

这是一个使用 Handler 的简单重复无效:

long mAnimStartTime;

Handler mHandler = new Handler();
Runnable mTick = new Runnable() {
    public void run() {
        invalidate();
        mHandler.postDelayed(this, 20); // 20ms == 60fps
    }
}

void startAnimation() {
    mAnimStartTime = SystemClock.uptimeMillis();
    mHandler.removeCallbacks(mTick);
    mHandler.post(mTick);
}

void stopAnimation() {
    mHandler.removeCallbacks(mTick);
}
于 2011-10-16T22:28:28.337 回答
4

由于这个问题有一些兴趣,我会回答。

最好的方法是有一个单独的画布线程。“单独的”画布只能通过SurfaceView. LunarLanding 就是一个很好的例子。每一帧都是单独计算的,而不是主视图,只共享 CPU 时间,而不是绘图时间。因此更快,即使结合了例如顶部的常规视图和底部的动画视图。

但是,如果您处于该共享环境中,则必须设置一个时间间隔。该间隔用于 FPS 上限。如果您没有设置 FPS 上限,那么 CPU 将疯狂运行以获得良好的动画效果,SurfaceView如果它是单独的。将其限制在 60fps 甚至更低的速度可以有效地绘制所有视图,而不会出现 CPU 过载。

所以请从 API 演示中查看月球着陆的绘图线程并设置 FPS 上限。

private long timeNow;
    private long timeDelta;
    private long timePrevFrame;

    private void capFps(int fps) {  
            timeNow = System.currentTimeMillis();
            timeDelta = timeNow - timePrevFrame;        

            try {

//ps 你总是可以为 60FPS 设置 16 而不是 1000/fps 以避免每次计算

Thread.sleep((1000 / fps) - timeDelta);
            } catch (InterruptedException e) {

            }   

            timePrevFrame = System.currentTimeMillis();
    }

然后绘图线程将如下所示:

@Override
    public void run() {
        Canvas c;

        while (run) {
            c = null;
            sleepFps(60, false);
            try {
                synchronized (surfaceHolder) {
                    c = surfaceHolder.lockCanvas(null);
                    widgetView.doDraw(c);
                }
            } finally {
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }

        }
    }
于 2011-10-12T03:15:51.733 回答