Monday, April 13, 2009

Android frame by frame animations

Frame by frame animations are traditional animations in the sense that they are created with a sequence of different images, played in order, like a roll of film. The AnimationDrawable class is the basis for frame animations.

This is a sample video of the Android Earth Animation application:


The animations is presented as a Button background and every time you touch it the animation stops and next time the rotational direction is changed (prograde and retrograde motion).

Usually, these animations are defined in XML resource files in the res/anim folder, using the tag and including the drawables composing th e animation.

Some information can be found at Android developers: Frame Animation, however if you want to automatically start the animation when the Activity is just started you'll find a hard time.
You may think that you can start the animation in onCreate or onResume, but it's not going to work.
The simplest solution is to delay the animation start using a timer in onResume:


/* (non-Javadoc) * @see android.app.Activity#onResume() */ @Override protected void onResume() { super.onResume(); (new Timer(false)).schedule(new AnimationTimer(earthButtonAnimation), 100); }



Where AnimationTimer is defined as


private static class AnimationTimer extends TimerTask { AnimationDrawable animation; public AnimationTimer(AnimationDrawable animation) { this.animation = animation; } @Override public void run() { animation.start(); this.cancel(); } }


As usual you can install or download the application or its source code from http://codtech.com/downloads/android.
Hope this helps and save you some time.

UPDATE:


Latest code, including some of the contributions, can be found at github.
Fell free to send me patches and corrections.

17 comments:

Unknown said...

Thanks! Very useful tip

Unknown said...

Hey man, really helpful for me.
Thanks!

Diego Torres Milano said...

Thank you both for your comments.

Unknown said...

Hello! This sample is indeed pretty helpful! I have a quick question for you.
You are using a timer and a timertask because an animation cannot be started from the onCreate, onPause and onResume function. It simply does not work (Android's bugs???)!
What does the usage of a timer bring? The code is executed in a secondary thread? Is it the fact that you add a delay before performing the task (100ms)!In this case, are we sure that 100ms is always long enough (in the case the code within onCreate, onStarted and onResume takes longer...)
Hopefully, I am clear enough! Looking forward to get your insight on this question! Thanks again for this very helpful piece of code!

Diego Torres Milano said...

Thanks for your comments.
The timer is used t delay a bit the animation start. It cannot be started straightaway, and you should figure out yourself if it's a bug or a feature :-)
In my case, the minimum delay is

private static final int DELAY = 20;

with DELAY = 19 the animation doesn't start. Your mileage may vary.
If you test, please share your results.

BTW, the animation runs on the main thread.

Unknown said...

Thanks a lot for your quick answer!
I tried to apply different delay. It happens that 90ms are required in my case.
Now, I am a little bit worried regarding the reliability of this workaround. How can we be sure that the behavior will be the same on any Android device (if some of them are less powerful than the emulator for instance)?
Regards and one more time thanks!

Diego Torres Milano said...

I will try to find some time to test in on some real phones next week.
100 ms could be a safe bet, 500 ms if you want safest and the user will not be even realizing the small delay on start.

Unknown said...

This would also work for starting the animation without a timer.

@Override
public void onWindowFocusChanged(boolean hasFocus){
explodeAnim.start();

}

Diego Torres Milano said...

Thanks for your comment.
This seems a lot better however I haven't tried it yet.

Unknown said...

thanks and how to access external file for animation.

ThomasCa said...

I found this very useful. Thank you.

The delayed timer didn't quite work for me, but I implemented something along a similar vein. Basically start a thread that check when the UI components have loaded up, then run the animation.

@Override
public void onResume(){
super.onResume();
new Thread(){
public void run(){
boolean ready = false;
while(!ready){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(iv_external.getWidth() > 0){
ready = true;
}
}
loading.start();
}
}.start();
}

Diego Torres Milano said...

Hi Thomas,
Thanks for your contribution.

Anonymous said...

Hi Diego :)

Is the download file still working? May I download it? The links seems to be broken. Thanks :)

Diego Torres Milano said...

Latest code, including some of the contributions, can be found at https://github.com/dtmilano/AndroidEarthAnimation.
Fell free to send me patches and corrections.

Aditya Pathak said...

i didn't found the code for this app.Can you please give me the link from where the code for this app can be downloaded because the links given by you have nothing to download..

Thanking you
Sam

Diego Torres Milano said...

The github link is correct as it's specified in the post's update.

What's the problem ?

Isra C. said...

It was so helpful to me :)