1

您好,我试图暂停动画 Drawable,但未能成功。在堆栈溢出的帮助下,我至少得到了 animationDrawable end listener 的帮助,这里是它的代码。是否有任何可能的方法可以暂停动画 Drawable 并从它暂停的位置开始...

public abstract class CustomAnimationDrawable extends AnimationDrawable{

    /** Handles the animation callback. */
    Handler mAnimationHandler;
    Runnable r= new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
               onAnimationFinish();
        }
    };

    public CustomAnimationDrawable(AnimationDrawable aniDrawable) {
        /* Add each frame to our animation drawable */
        for (int i = 0; i < aniDrawable.getNumberOfFrames(); i++) {
            this.addFrame(aniDrawable.getFrame(i), aniDrawable.getDuration(i));
        }
    }

    @Override
    public void start() {
        super.start();
        /*
         * Call super.start() to call the base class start animation method.
         * Then add a handler to call onAnimationFinish() when the total
         * duration for the animation has passed
         */
        mAnimationHandler = new Handler();
        mAnimationHandler.postDelayed(r, getTotalDuration());

    }

    /**
     * Gets the total duration of all frames.
     * 
     * @return The total duration.
     */
    public int getTotalDuration() {

        int iDuration = 0;

        for (int i = 0; i < this.getNumberOfFrames(); i++) {
            iDuration += this.getDuration(i);
        }

        return iDuration;
    }

    /**
     * Called when the animation finishes.
     */
    abstract void onAnimationFinish();

     public void destroy()
    {


         mAnimationHandler.removeCallbacksAndMessages(r);
         mAnimationHandler.removeCallbacksAndMessages(null);


    }

}

请帮助我有什么办法可以暂停吗?

4

3 回答 3

7

我一直在环顾四周,似乎没有办法直接做到这一点。AnimationDrawable 中用于设置帧的所有变量和方法都是私有的。但是,您可以在点击暂停时获取动画所在帧的索引,然后通过从播放的最后一帧的索引迭代原始动画来创建新动画(然后重新开始并添加其余动画,如果动画是周期性的)。

我从一个基于 XML 的动画循环开始,然后添加了另一个用于暂停和恢复的循环。这就是我最终做的事情,到目前为止它工作正常,首先列出了相关变量。

private ImageView sphere;
private AnimationDrawable sphereAnimation;
private AnimationDrawable sphereResume;
private AnimationDrawable activeAnimation;
private Drawable currentFrame;
private Drawable checkFrame;
private int frameIndex;

private void pause()
{
    looping = false;
    sphereResume = new AnimationDrawable();
    activeAnimation.stop();
    currentFrame = activeAnimation.getCurrent();

    frameLoop:
    for(int i = 0; i < sphereAnimation.getNumberOfFrames(); i++)
    {
        checkFrame = activeAnimation.getFrame(i);

        if(checkFrame == currentFrame)
        {
            frameIndex = i;
            for(int k = frameIndex; k < activeAnimation.getNumberOfFrames(); k++)
            {
                Drawable frame = activeAnimation.getFrame(k);
                sphereResume.addFrame(frame, 50);
            }
            for(int k = 0; k < frameIndex; k++)
            {
                Drawable frame = activeAnimation.getFrame(k);
                sphereResume.addFrame(frame, 50);
            }
            activeAnimation = sphereResume;
            sphere.setImageDrawable(activeAnimation);
            sphere.invalidate();
            break frameLoop;
        }
    }
}

private void play()
{
    looping = false;
    activeAnimation.setOneShot(true);
    activeAnimation.start();
}

private void stop()
{
    looping = false;
    activeAnimation.stop();
    activeAnimation = sphereAnimation;
    sphere.setImageDrawable(activeAnimation);
}

private void loop()
{
    looping = true;
    stopSoundEffect();
    activeAnimation.setOneShot(false);
    activeAnimation.start();
}
于 2012-11-28T20:14:17.257 回答
0

Zorbert Crenshaw 的方法很好,但很复杂。

我有另一个解决方案。(需要用 try/catch 包围,因为反射是不安全的)。

您可以调用getCurFrameFromAnimationDrawable在停止动画之前保存当前帧,并调用setCurFrameToAnimationDrawable从任何帧开始。

'30L' 应该替换你的持续时间参数。

private int getCurFrameFromAnimationDrawable(AnimationDrawable drawable){
    try {
        Field mCurFrame = drawable.getClass().getDeclaredField("mCurFrame");
        mCurFrame.setAccessible(true);
        return  mCurFrame.getInt(drawable);
    }catch (Exception ex){
        Log.e(AnimTool.class.getName(), "getCurFrameFromAnimationDrawable: Exception");
        return 0;
    }
}

private void setCurFrameToAnimationDrawable(AnimationDrawable drawable, int curFrame){
    try {
        Field mCurFrame = drawable.getClass().getDeclaredField("mCurFrame");
        mCurFrame.setAccessible(true);
        mCurFrame.setInt(drawable, curFrame);
        Class[] param = new Class[]{Runnable.class, long.class};
        Method method = Drawable.class.getDeclaredMethod("scheduleSelf", param);
        method.setAccessible(true);
        method.invoke(drawable, drawable, 30L);
    }catch (Exception ex){
        Log.e(AnimTool.class.getName(), "setCurFrameToAnimationDrawable: Exception");
    }
}
于 2017-03-03T02:58:18.200 回答
0

这是对这个问题的迟到回答。但它可能对另一个有帮助。要暂停和恢复 AnimationDrawable,只需对其进行自定义并仅使用一个变量进行处理。

class CustomAnimationDrawable1() : AnimationDrawable() {

private var finished = false
private var animationFinishListener: AnimationFinishListener? = null
private var isPause = false
private var currentFrame = 0

fun setFinishListener(animationFinishListener: AnimationFinishListener?) {
    this.animationFinishListener = animationFinishListener
}

interface AnimationFinishListener {
    fun onAnimationFinished()
}


override fun selectDrawable(index: Int): Boolean {
    val ret = if (isPause) {
        super.selectDrawable(currentFrame)
    } else {
        super.selectDrawable(index)
    }

    if (!isPause) {
        currentFrame = index
        if (index == numberOfFrames - 1) {
            if (!finished && ret && !isOneShot) {
                finished = true
                if (animationFinishListener != null) animationFinishListener!!.onAnimationFinished()
            }
        }
    }
    return ret
}

fun pause() {
    isPause = true
}

fun resume() {
    isPause = false
}

}

于 2019-01-09T06:38:28.883 回答