Create animated splash screen using frames on Andr

2019-01-26 21:15发布

问题:

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.

回答1:

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);
}


回答2:

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. >)



回答3:

i tried all of those solution with each one getting better :D i could use more frame and more resolution but still not satisfying to managers :( i found best solution is to use video instead of frames it works like a charm for even low memory devices i tested 150 frames each of size 480*854 with a video codec (H.264 mp4) on xperia u with 256mb of ram