How can I change the duration for an Android AnimationDrawable animation on-the-fly?

android

Solution

I had the same problem but I managed to solve it when reading the source code of AnimationDrawable by implementing my own AnimationDrawable class that extends AnimationDrawable and override the `Run()` method and add `setDuration()` method which allows me to set the duration as follow:

By reviewing the original run method we see that it do the same but by calling `scheduleSelf(this, SystemClock.uptimeMillis() + duration);` with the duration you specified when adding the frame so I changed it. I also add duration because I use the same for all my frames but you can use array of new duration.

import android.graphics.drawable.AnimationDrawable;
import android.os.SystemClock;

public class MyAnimationDrawable extends AnimationDrawable {

    private volatile int duration;//its volatile because another thread will update its value
    private int currentFrame;

    public MyAnimationDrawable() {
        currentFrame = 0;
    }

    @Override
    public void run() {
        int n = getNumberOfFrames();
        currentFrame++;
        if (currentFrame >= n) {
            currentFrame = 0;
        }
        selectDrawable(currentFrame);
        scheduleSelf(this, SystemClock.uptimeMillis() + duration);
    }

    public void setDuration(int duration) {
        this.duration = duration;
        //we have to do the following or the next frame will be displayed after the old duration
        unscheduleSelf(this);
        selectDrawable(currentFrame);
        scheduleSelf(this, SystemClock.uptimeMillis()+duration);
    }
}

It's my first answer so I hope it helps you and it's explained well.

Problem

I'm new to Android platform. I'm using the following to animate a set of 16 "frames" using AminationDrawable in my app: In the XML file I have: ``` <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/image_1" android:duration="200" /> <item android:drawable="@drawable/image_1_25" android:duration="200" /> <item android:drawable="@drawable/image_1_5" android:duration="200" /> <item android:drawable="@drawable/image_1_75" android:duration="200" /> <item android:drawable="@drawable/image_2" android:duration="200" /> <item android:drawable="@drawable/image_2_25" android:duration="200" /> <item android:drawable="@drawable/image_2_5" android:duration="200" /> <item android:drawable="@drawable/image_2_75" android:duration="200" /> <item android:drawable="@drawable/image_3" android:duration="200" /> <item android:drawable="@drawable/image_3_25" android:duration="200" /> <item android:drawable="@drawable/image_3_5" android:duration="200" /> <item android:drawable="@drawable/image_3_75" android:duration="200" /> <item android:drawable="@drawable/image_4" android:duration="200" /> <item android:drawable="@drawable/image_4_25" android:duration="200" /> <item android:drawable="@drawable/image_4_5" android:duration="200" /> <item android:drawable="@drawable/image_4_75" android:duration="200" /> </animation-list> ``` In the Java code I have the following first I'm declaring the class and adding an `onCreate()` method where I set up the animation. ``` public class MyNewActivity extends Activity { // member variables (accessible from within class methods below). AnimationDrawable mainAnimation; long mSpeed = 50; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_widget); // set up image ImageView mainImage = (ImageView) findViewById(R.id.image_widget); mainImage.setBackgroundResource(R.drawable.animated_image); mainAnimation = (AnimationDrawable) mainImage.getBackground(); }; <...snip...> ``` ...then later on I start my drawing when the user presses a button I call the following to start the animation moving: ``` private void start() { // start the image rotating. if (mainAnimation.isRunning()) mainAnimation.stop(); int numFrames = mainAnimation.getNumberOfFrames(); for (int ii = 0; ii < numFrames; ii++ ) { // change the animation speed. Drawable d = mainAnimation.getFrame(ii); mainAnimation.scheduleDrawable(d, mainAnimation, mSpeed); } } <...snip...> ``` So elsewhere in the code I have a place to adjust the member variable `mSpeed`. If I do this and then call `start()`, the animation will start, however the speed is always the same (essentially what was defined in the XML above. My question is, how can I modify the "duration" of the frames to move this animation faster/slower based on user input? I see no way to modify a "duration" state, and was under the assumption the `ScheduleDrawable()` call above would change the drawing's frames duration.

Original source