Android: make animation from still images

50,696

Solution 1

OK. The biggest problem and the easiest solution I got to go with after so many days. I would never expect that it would be so easy to do... :D

I've used both handler and timer to achieve with just an image view, no flipper, no animator nothing else at all... Here is my solution:

----- main.xml file -----

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background">

<ImageView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/imageView1">
</ImageView>

And here is the way I have done it:

public class MainActivity extends Activity {
private ImageView _imagView;
private Timer _timer;
private int _index;
private MyHandler handler;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    handler= new MyHandler();
    _imagView=(ImageView) findViewById(R.id.imageView1);

    _index=0;
    _timer= new Timer();
    _timer.schedule(new TickClass(), 500, 200);
}

private class TickClass extends TimerTask
{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        handler.sendEmptyMessage(_index);
        _index++;
    }
}

private class MyHandler extends Handler
{
    @Override
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        super.handleMessage(msg);

        try {
                Bitmap bmp= BitmapFactory.decodeStream(MainActivity.this.getAssets().open("drum_"+_index+".png"));
                _imagView.setImageBitmap(bmp);

                Log.v("Loaing Image: ",_index+"");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.v("Exception in Handler ",e.getMessage());
        }
    }
}

}

Note: I've placed all my images to asset directory.

Its so simple as it can, nothing big to do...

I hope it'll be helpful for someone looking to go like this :)

Solution 2

Use a FrameAnimation, eg in res/drawable/movie.xml:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/frame1" android:duration="50" />
    <item android:drawable="@drawable/frame2" android:duration="50" />
    <item android:drawable="@drawable/frame3" android:duration="50" />
    etc...
</animation-list>

And then in Java:

imageView.setBackgroundResource(R.drawable.movie);
AnimationDrawable anim = (AnimationDrawable) imageView.getBackground();
anim.start();

Solution 3

Loading several images is very expensive.

I think it's better to load a single image containing all the movements of that certain animation. An animation strip.

private Bitmap animation = BitmapFactory.decodeResource(getResources(), R.drawable.myPng);

The idea is to traverse the bitmap.

Solution 4

Well, I'm using viewFlipper, switching between views. Good thing about this one is that u can see previous picture sliding out while the new one slides in.

Inside image displaying method:

    if (direction == NEXT) {
        viewFlipper.setInAnimation(slideLeftIn);
        viewFlipper.setOutAnimation(slideLeftOut);

        if (currImg < max)
            currImg++;
        if (currImg == max)
            currImg = 0;

        if (currentView == 0) {
            currentView = 1;
            ImageView iv = (ImageView) findViewById(R.id.ImageView02);
            iv.setImageResource(images[currImg]);
        } else if (currentView == 1) {
            currentView = 2;
            ImageView iv = (ImageView) findViewById(R.id.ImageView03);
            iv.setImageResource(images[currImg]);
        } else {
            currentView = 0;
            ImageView iv = (ImageView) findViewById(R.id.ImageView01);
            iv.setImageResource(images[currImg]);
        }
        viewFlipper.showNext();
    }
    else if (direction == PREV) {
        viewFlipper.setInAnimation(slideRightIn);
        viewFlipper.setOutAnimation(slideRightOut);

        if (currImg > 0)
            currImg--;
        else if (currImg <= 0)
            currImg = (max-1);

        if (currentView == 0) {
            currentView = 2;
            ImageView iv = (ImageView) findViewById(R.id.ImageView03);
            iv.setImageResource(images[currImg]);
        } else if (currentView == 2) {
            currentView = 1;
            ImageView iv = (ImageView) findViewById(R.id.ImageView02);
            iv.setImageResource(images[currImg]);
        } else {
            currentView = 0;
            ImageView iv = (ImageView) findViewById(R.id.ImageView01);
            iv.setImageResource(images[currImg]);
        }
        viewFlipper.showPrevious();

And inside XML file:

        <ViewFlipper android:id="@+id/imageflipper"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <ImageView android:id="@+id/ImageView01"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"        
            android:scaleType="centerInside"        
            android:layout_gravity="center" />

        <ImageView android:id="@+id/ImageView02"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"        
            android:scaleType="centerInside"        
            android:layout_gravity="center" />

        <ImageView android:id="@+id/ImageView03"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"        
            android:scaleType="centerInside"        
            android:layout_gravity="center" />

        </ViewFlipper>
Share:
50,696

Related videos on Youtube

Mudasser Hassan
Author by

Mudasser Hassan

Currently working at Sixlogics as Development Team Lead. Android, ASP.NET/C#/VB.NET (Framework 2.0, 3.0, 3.5, 4.0) Developer. Database (MSSQL 2005/2008) Developer. Application Analyst and Designer. System Architect.

Updated on February 09, 2020

Comments

  • Mudasser Hassan
    Mudasser Hassan about 4 years

    I've a series of still images and total of more than 500 images presented in drawable directory. I need to make an animation (load about 20 images per second). I want it to run smoothly and with no Out Of Memory Exception.

    I've idea to do this that images for 2 to 3 seconds (40 to 60 images) should load in memory and displayed and then they should disposed off (release the memory) and then images for next 2 to 3 seconds should load. This technique can prevent Out Of Memory Exception. Its just an idea, I dont know whether its a good idea or not. Please guide me some better idea with some code to go with... If my idea is much better and can work then please tell me some helping code to do that.

    After reading replies and doing as you suggest, I've written some code like this:

      <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/llMain">
    
    <ViewFlipper android:id="@+id/imageflipper"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    <ImageView android:id="@+id/ImageView01"
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent"        
            android:scaleType="centerInside"        
            android:layout_gravity="center" />
        </ViewFlipper>
        </LinearLayout>
    

    and here is my code for doing animation:

    public class Animation extends Activity {
    ViewFlipper flipper;
    int myIndex = 216;
    private final Handler handler = new Handler();
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        flipper=(ViewFlipper)findViewById(R.id.imageflipper); 
        doTheAutoRefresh();
            //displayData();
    }
    
    private void doTheAutoRefresh() {
        handler.postDelayed(new Runnable() {
            public void run(){
                displayData(); // this is where you put your refresh code
                doTheAutoRefresh();
                 }
             }, 30);
    
    }
    
    private void displayData()
    {
        Resources r = getResources();
        if(myIndex > 230){
            myIndex = 216;
            ImageView myImg = (ImageView)findViewById(R.id.ImageView01);
            myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation"));
    
            myIndex += 1;
            flipper.showNext();
        }
        else{
            ImageView myImg = (ImageView)findViewById(R.id.ImageView01);
    
            myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation"));
    
            myIndex += 1;
            flipper.showNext();
        }
    }
    

    }

    but its very slow. I've set up the refresh time to 30 milliseconds but actually its not refreshing too fast rather its refresh time is about 1 second. Any suggestion to make it fast to feel like real animation?

    Thanks,

  • Mudasser Hassan
    Mudasser Hassan about 13 years
    Sprite is not my case. I told u that I have more than 500 images. 1st I cannot make a strip of 500 images, if I make however, I think its wont be possible to load that HUGE strip or it wont be a good approach... Looking for some better idea...
  • Mudasser Hassan
    Mudasser Hassan about 13 years
    there are still 2 things I am confused about. 1st, where is the recycling code? How are you recycling the old images and loading the new? 2nd, I want to make an animation, not flip the images left or right rather smooth animation (new images loading and old images unloading automatically)... I am new to Android, and also dont know much about JAVA. Any code sample will be really helpful and appreciated... :)
  • yosh
    yosh about 13 years
    Well, Java has garbage collector so you don't have to manually release memory like in obj-c for iphone etc. You can use system.gc() to force start garbage collector. The iv.setImageResource() is changing the image in imageview and I declare 2 animations (for old and new picture) that will be used to animate the switch. If you want auto animation instead gestures just add some timer and use the above method like every 2 seconds or smth. Ofc, declare animations from xml and keep the value of direction (in my case i needed NEXT or PREV).
  • Mudasser Hassan
    Mudasser Hassan about 13 years
    I've done something reading your code and also after exploring more on other posts/sites. I edited my question and added my code to it. Its refreshing is toooooo slow. I want to make it very fast to feel like real animation. Any suggestion? Thanks
  • Mudasser Hassan
    Mudasser Hassan about 13 years
    will it work for 500 images without OutOfMemoryException? Will it call gc() after drawing each image? and what out PAUSE/RESUME/STOP/PLAY kind of stuff? Can I make these functionality with this approach?
  • olivierg
    olivierg about 13 years
    I haven't tried with so many images, but it's handled by the Android framework, so it's supposed to be smart. I'm pretty sure that it handles memory nicely. That said, it's maybe not adequate for a full fledged video... Why don't you turn your images into a video, put it into res/raw, and then play it with MediaPlayer: it's very easy, plus it got pause, play, seek and all that. And the compression will be better, possibly much better...
  • Mudasser Hassan
    Mudasser Hassan about 13 years
    thanks a lot. Video wont resolve my problem I think as I am trying to develop some application like Talking Santa. You can check it here link
  • Mudasser Hassan
    Mudasser Hassan about 13 years
    And now I tried the technique mentioned at this link link (last 1 I tried) with a little change in the loop that I am calling codesystem.gc() after adding each image to ViewFlipper. So far, its looking great except loading (loading of app is slow). Your suggestion on this will be highly appreciated. :)
  • Peterdk
    Peterdk over 11 years
    This is causing out of memory errors, because it looks like it loads them all in memory.
  • Md Maidul Islam
    Md Maidul Islam about 9 years
    @Mudasser Hassan if all images in server side and I have to download all images and do that type of work. (playing a video or image animating) . how can I do that.I need all images showing like 360 degree rotating a single image.Like that mathieusavard.info/threesixty/demo.html
  • Md Maidul Islam
    Md Maidul Islam about 9 years
    Thanks. If all images is from server and we have to download all images and show. Did you give some idea? I am facing issue on that. Please help.
  • Mixaz
    Mixaz over 7 years
    If you used Handler.post() the code would be shorter. Another matter is that you decode image on UI thread, that's not good. More elegant solution would be to decode next image in background (using AsyncTask) in advance and display it after 200 ms or after image has been decoded, if it takes more time.

Related