Reputation: 334
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:
AnimationDrawable
is finished?Upvotes: 2
Views: 1905
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
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
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
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