«

»

Feb 07

Some things I learned about Android's Frame animation

Hi

Just a quick share of lessons learned about Android's Frame-by-Frame animations. Some of the functionality is poorly documented, as many people point out, so the web is the only place for answers. Having looked for some answers to these questions and couldn't find any - here's what I found out myself.

Update [2/3/11]: A new post on this topic gives a more broad view of my experience.

Resetting Frame Animation

The API is a bit weird here, because the restart function is inside the setVisible function of AnimationDrawable. If you don't restart and just do another start() on an already finished animation - it will just jump to the last frame. You must reset the animation before starting it.

However if you do setVisible(true,true) your animation will run twice!, so you must do setVisible(false,true);. This will reset the animation for a start() operation.

Preloading Animations

I got to preloading animations after understating that trying to fire an animation "right off the XML", has a lag of over a second. This must be due to the inflation process. And I was looking for snappy smooth animations right away, without waiting for them to inflate, so naturally I needed to preload them. But how?

So I loaded the frame animation into an ImageView with android:visibility="gone", and "hijacked" its drawable when I needed to fire it:

The XML, just put it somewhere in your main xml so it will be inflated when the app starts.

<!-- Preload animations -->
<ImageView android:id="@+id/anim_preloaded_imgview" 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:src="@drawable/myanim"
	android:visibility="gone" />

The Java:

ImageView animateHere = (ImageView) findViewById(R.id.animate_here);
animateHere.setImageDrawable(((ImageView)findViewById(R.id.anim_preloaded_imgview).getDrawable());
AnimationDrawable anim = (AnimationDrawable) animateHere.getDrawable();
anim.setVisible(false, true); //reset! see previous section
anim.start(); //now good to start, even if already fired before

Voila.

OutOfMemory expection? srsly?

So at the beginning I was getting a lot of OutOfMemory exceptions on the loading of the animations. Probably due to loading many big bitmaps into the memory. So I reduced the size of my PNGs to ~80,000 pixels (images are ~200x400), and then I was able to load as many as I wanted! Strange...
I didn't really research what's the limit, but using ~140,000 pixels did not fly.

In these cases mogrify is your friend. This will resize all images beginning with "myanim" to 200xWhatever keeping aspect ratio:

mogrify -resize 200 myanim*

That's it for now
But tomorrow I will learn more. Android is surprising..

Please comment if you [dis]agree, and share your own experience!
Roy.

Share
  • martin

    Hi. I've been going around in circles for hours now.

    I've copy-pasted a lot of "solutions" and really tried to understand all the errors I get, but I'm getting nowhere.

    I think I'm making progress with your code, but my question is,

    your xml-id called "animate_here", how does it look like?

    Cause I referred to my drawable-xml that held an animation-list, and it's not working at all.

  • http://www.morethantechnical.com Roy

    Martin, please check out my new post on this subject here, it has more code examples.

    Roy.

  • martin

    Thank you for answering. I checked out the new post, which was very good, but I found my solution in doing almost like you did the first time but within the "windowfocuschanged"-method. I didn't use the setDrawable though, I used the setBackgroundResource. Cheers!

  • Matt

    Using the AnimationDrawable class for Android is damn F'ing damn nightmare, this thing is worthless. It is potentially the worst 3rd party class I have ever had the curse of having to use. Whoever wrote it should be fired...out of a cannon...into the sun.

    For instance, in one case I have a program where when you touch the screen I would play an animation. Something like:

    TestAnimDrawable.start();

    would presumably work, as that is the example given on the documentation page. However, in reality it doesn't do a damn thing.

    TestAnimDrawable.run();

    on the other hand does do something, but it completely ignores the fact that I set duration times for each frame in the XML.

    Aside from that, getting this hell-hole of a class to work with a live wallpaper was also a disaster. If anyone comes across that problem, here is some code that worked for me which I found on the net and had to tweak a bit. The big challenge here is the wallpaper doesn't have an imageview.

    Resources res = context.getResources();
    TestAnimDrawable = (AnimationDrawable) res.getDrawable(R.drawable.testanim);
    TestAnimDrawable.setVisible(false,true);

    In the end I still don't have animations working as any normal human being would expect, but I appreciate the information here, which is why I add what I know from my own experiences. If the author has a more complete example I would very much so be interested but...In the end I think I will just write my own animation class and stop getting F'ed around by this garbage which clearly some idiot must have written originally.

    I feel your pain Roy.

  • Sagar Raiyani

    it's a nornal animation dude...........