如何在android中绘制动画视图?

时间:2011-10-01 12:15:22

标签: android android-layout android-canvas android-view

我从头开始创建自定义视图。延长View并覆盖onDraw()。 当关闭动画视图时,我使用偏移生成自定义动画。 例如。

while(!isOnTop){
mOffset++;

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

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

}

我的想法是我的框架来自于自我失效。问题是这个视图的失效只能通过在同一个屏幕上滚动列表视图来实现。

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

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

执行动画的唯一解决方案是,例如10个失效请求的步长更大?它会缓解延迟,但我想我可以采用不同的方法。

2 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:4)

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

最好的方法是使用单独的画布线程。只能使用SurfaceView来实现“单独”画布。 LunarLanding是这种用法的一个很好的例子。每个帧的分别计算的主视图仅共享CPU时间,而不是绘图时间。因此,即使结合了例如顶部的常规视图和底部的动画视图,也会更快。

但如果您在共享环境中,则必须设置间隔。该间隔用于FPS上限。如果你没有设置FPS上限,那么CPU将运行疯狂管理以获得SurfaceView的好动画(如果它是独自的话)。以60fps甚至更低的速度限制它将有效地绘制所有视图而无CPU过载。

请参阅API演示中的Lunar Landing绘图线程并设置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);
                }
            }

        }
    }