Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create animated splash screen using frames on Android

So here's the deal, I've searched every single question and link online but none are helpful. I have 120 frames of an animation in .jpg format for my splash screen. I understand that jpegs are converted to bitmaps on memory so that's why I get an OutOfMemoryError. The maximum frames I get to animate are 10. Is there any way to do this frame by frame, or should I try something else. Here's my code:

    final AnimationDrawable anim = new AnimationDrawable();
    anim.setOneShot(true);

    for (int i = 1; i <= 120; i++) 
    {
        Drawable logo = getResources().getDrawable(getResources()
                  .getIdentifier("l"+i, "drawable", getPackageName()));

        anim.addFrame(logo, 50);
        if (i % 3 == 0)
        {
            System.gc();
        }
    }

    ImageView myImageView = (ImageView) findViewById(R.id.SplashImageView);
    myImageView.setBackgroundDrawable(anim);
    myImageView.post(new Runnable()
    {
       public void run()
       {
          anim.start();
       }
    });

I've placed the 120 jpegs under the drawable folder with an "l" prefix (eg l1, l2 etc). I do garbage collection every 3 jpegs but that won't do a thing.

like image 624
Crew Peace Avatar asked Sep 04 '26 22:09

Crew Peace


2 Answers

You can try to do it without AnimationDrawable using Handler.postDelayed. Something like this:

final ImageView image = (ImageView) findViewById(R.id.SplashImageView);
final Handler handler = new Handler();

final Runnable animation = new Runnable() {
    private static final int MAX = 120;
    private static final int DELAY = 50;

    private int current = 0;

    @Override
    public void run() {
        final Resources resources = getResources();
        final int id = resources.getIdentifier("l" + current, "drawable", getPackageName());
        final Drawable drawable = resources.getDrawable(id);

        image.setBackgroundDrawable(drawable);
        handler.postDelayed(this, DELAY);
        current = (current + 1) % MAX;
    }
};

handler.post(animation);

This solution requires less memory because it keeps only one drawable at the time.

You can cancel the animation using handler.removeCallbacks(animation);.

If you want make a one-shot animation you can call handler.postDelayed conditionally:

if (current != MAX - 1) {
    handler.postDelayed(this, DELAY);
}
like image 199
Vladimir Mironov Avatar answered Sep 07 '26 12:09

Vladimir Mironov


Y̶o̶u̶ ̶n̶e̶e̶d̶ ̶t̶o̶ ̶c̶a̶l̶l̶ ̶.̶r̶e̶c̶y̶c̶l̶e̶(̶)̶ ̶o̶n̶ ̶t̶h̶e̶ ̶b̶i̶t̶m̶a̶p̶s̶ ̶y̶o̶u̶ ̶d̶o̶n̶'̶t̶ ̶u̶s̶e̶ ̶a̶n̶y̶m̶o̶r̶e̶.̶ ̶O̶t̶h̶e̶r̶w̶i̶s̶e̶ ̶t̶h̶e̶y̶ ̶w̶o̶n̶t̶ ̶b̶e̶ ̶g̶a̶r̶b̶a̶g̶e̶ ̶c̶o̶l̶l̶e̶c̶t̶e̶d̶ ̶p̶r̶o̶p̶e̶r̶l̶y̶.̶

Also in the manifest set uses large heap to true. This gives you a bit more space to breathe. >)

like image 39
pumpkee Avatar answered Sep 07 '26 13:09

pumpkee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!