750 frame transparent PNG animation in ImageView a

2019-08-31 06:24发布

问题:

I have an Activity with two ImageViews set to full screen 320 x 480.

I need to play an animation but couldn't get more than 50 to play using AnimateDrawable and an xml array before running out of VM.

I'm trying to switch PNGs with a Loop so I can do other stuff at points along the way. For example vibrate at frames 120, 180 & 250 etc. and play another animation at frame 400.

This code below works but the ImageView takes between 180 - 280ms to update on the emulator. So I need to set thread.sleep greater than 280-300 otherwise I start missing frames. I need a quicker way to update the imageview. Is there a quicker widget available?

The image for some frames do not need to change or are blank so while the animation lasts for 746 frames I only actually need 245 of them. So I have deleted the non changing or blank frames from the drawables folder and the code skips over them when not found. This has reduced the size down to 9mb total for all the images.

This is my first Android app so sorry if I am not doing it the right way. I will take any advice on how to improve. :-)

Can anyone think of a better way to do this? HELP!! (This same logic works fine on the iPhone)

activity_main.xml

xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<ImageView
    android:id="@+id/background"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:scaleType="fitXY"
    android:src="@drawable/imgbackground"
    android:visibility="visible" />

<ImageView
    android:id="@+id/animLayer"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:visibility="visible" />

</RelativeLayout>

MainActivity.java

package com.test.pngloop

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.ImageView;

public class MainActivity extends Activity {
    private static final String TAG = null;
    public int iFrameCount = 0;
    public ImageView myIV;
    public String myString;

    long startTime;
    long endTime;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
             //define the IV here so it's done only once
    myIV = (ImageView) findViewById(R.id.animLayer);
}

 @Override
 protected void onStart()
{
        super.onStart();
    Thread thr1 = new Thread(r1);
    thr1.start();
}


Runnable r1 = new Runnable() 
{
    public void run() 
    {
        while (iFrameCount< 747) 
        {
                  runOnUiThread(new Runnable() 
      {
          public void run() 
          {
              iFrameCount++;
        String image="image" + iFrameCount;
                    int resID = getResources().getIdentifier(image, "drawable", getPackageName()); 
              if (resID != 0)    //if there is no image/change for this frame skip it
              {
            myString="iFrameCount: " + iFrameCount;
            Log.d(TAG, myString);

                              //speed the same between setImageResource & setBackgroundResource
                  //myIV.setImageResource(resID);
                  //myIV.postInvalidate();

               startTime = System.currentTimeMillis();
                                 myIV.setBackgroundResource(resID);
                     endTime = System.currentTimeMillis();
                     System.out.println("setBackground took: " + (endTime - startTime) + " milliseconds");

              }
              else
              {  //we can skip frames 1-119, 209-251, 272-322, 416-472 & 554-745 (as no change from previous frame)
                myString="File skipped: " + iFrameCount;
                Log.d(TAG, myString);
              }

         }
     });

     try 
     {
         Thread.sleep(300);
     }
     catch (InterruptedException iex) {}

             }
          Log.d(TAG, "Finished playing all frames");     
         }
   };

}

回答1:

I have now been able to get the frame rate up to close to 20 frames a second by reducing the size of each image (used in the animation) down to the smallest vertical strip to fit the object.

I came up with this idea after reading about using Spritesheets for game animation where they move a single image around and view the needed frame through a small window. Sprites were not practicle for my purpose, too many frames Sprite sheet would be 135mb.

The images are now only 480 x 150 (between 31-54KB each) instead of a full screen. ImageView height is set to fill_parent and ImageView width set to wrap_content so it still scales automatically to different screen sizes.

I found that now the files are much smaller it loads quicker and now is close to an acceptable animation frame rate. Hope this is of help to anyone else who is trying the same thing.