Andrew
Andrew

Reputation: 334

AnimationDrawable.isRunning() always return true

I faced a strange behavior. If I start AnimationDrawable with start(), then after animation is finished, method isRunning() will still return true. It is "one-shot" animation, which is not looped.

Here is an example code:

public class MyActivity extends Activity {
    private AnimationDrawable cartoon;
    private ImageView iv;
    private BitmapDrawable frame0, frame1;
    private final int sleep=1000;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        cartoon = new AnimationDrawable();
        cartoon.setOneShot(true);
        frame0 = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.gridx0));
        frame1 = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.gridx1));
    }

    @Override
    protected void onStart() {
        super.onStart();
        if(iv==null) iv = (ImageView) findViewById(R.id.imageView);
        cartoon.addFrame(frame0, sleep);
        cartoon.addFrame(frame1, sleep);
        iv.setImageDrawable(cartoon);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(cartoon.isRunning()) Log.d("AnimationTest", "Animation already started");
        else cartoon.start();
        return true;
    }
}

And here is output:

02-22 14:18:42.187: DEBUG/AnimationTest(2043): Animation already started
02-22 14:18:52.093: DEBUG/AnimationTest(2043): Animation already started
02-22 14:18:52.166: DEBUG/AnimationTest(2043): Animation already started
...and so on.

So animation runs for the first time and then isRunning will return true forever. I also found similar issue posted to code.google.com, but it was closed w/o any comments

My questions is:

  1. Is there a real bug or did I misunderstood something?
  2. How can I tell when AnimationDrawable is finished?

Upvotes: 2

Views: 1905

Answers (4)

cVoronin
cVoronin

Reputation: 1350

On way to handle animation's end is to calculate the total animation's duration and to send an event after that duration is expired.

    private AnimationDrawable timerAnimation;

...

private void startTimerAnimation() {
    int timerAnimationDuration = calcTimerAnimationDuration();
    timerAnimation.start();
    timerAnimationEndHandler.sendEmptyMessageDelayed(0, timerAnimationDuration);
}


private int calcTimerAnimationDuration() {
    int total = 0;
    for (int i = 0; i < timerAnimation.getNumberOfFrames(); i++) {
        total += timerAnimation.getDuration(i);
    }
    return total;
}


private Handler timerAnimationEndHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        onTimerAnimatonFinished();
};

Upvotes: 0

Geobits
Geobits

Reputation: 22342

After taking a look at the source, I can only come to the conclusion that setting it to oneshot means it truly is a oneshot animation, with no repeat. At least, not without calling stop() first.

If you call stop() once it's done, then the next call to start() works fine(in my test, at least). How you call stop() is up to you, but you could schedule a timer to run it after the total duration has elapsed when you call start(). Not having callbacks in this class does kinda suck.

If you'll be using this mechanism often, it might be worth extending AnimationDrawable to give it callbacks. If you do, you should post it up somewhere to make it easier on yourself and others in the future.

Upvotes: 1

Nikola Despotoski
Nikola Despotoski

Reputation: 50578

Try extending AnimationDrawable, declare your own boolean field that will be used as flag. Override isRunning() and return the boolean field instead. Change the flag based on your class animation listener (start, repeat, end). :)

Upvotes: 1

Opiatefuchs
Opiatefuchs

Reputation: 9870

What happens if You try:

    @Override
public boolean onTouchEvent(MotionEvent event) {
    if(cartoon.isRunning()){
      Log.d("AnimationTest", "Animation already started");
      return false;
   }else{
       cartoon.start();
      return true;
    }

}

Upvotes: -1

Related Questions