FileDocCategorySizeDatePackage
AnimationDrawable.javaAPI DocAndroid 1.5 API11516Wed May 06 22:42:00 BST 2009android.graphics.drawable

AnimationDrawable

public class AnimationDrawable extends DrawableContainer implements Runnable
An object used to create frame-by-frame animations, defined by a series of Drawable objects, which can be used as a View object's background.

The simplest way to create a frame-by-frame animation is to define the animation in an XML file, placed in the res/drawable/ folder, and set it as the background to a View object. Then, call {@link #run()} to start the animation.

An AnimationDrawable defined in XML consists of a single <animation-list> element, and a series of nested <item> tags. Each item defines a frame of the animation. See the example below.

spin_animation.xml file in res/drawable/ folder:

<!-- Animation frames are wheel0.png -- wheel5.png files inside the
res/drawable/ folder -->
<animation-list android:id="selected" android:oneshot="false">
<item android:drawable="@drawable/wheel0" android:duration="50" />
<item android:drawable="@drawable/wheel1" android:duration="50" />
<item android:drawable="@drawable/wheel2" android:duration="50" />
<item android:drawable="@drawable/wheel3" android:duration="50" />
<item android:drawable="@drawable/wheel4" android:duration="50" />
<item android:drawable="@drawable/wheel5" android:duration="50" />
</animation-list>

Here is the code to load and play this animation.

// Load the ImageView that will host the animation and
// set its background to our AnimationDrawable XML resource.
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.spin_animation);

// Get the background, which has been compiled to an AnimationDrawable object.
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

// Start the animation (looped playback by default).
frameAnimation.start()
attr
ref android.R.styleable#AnimationDrawable_visible
attr
ref android.R.styleable#AnimationDrawable_variablePadding
attr
ref android.R.styleable#AnimationDrawable_oneshot
attr
ref android.R.styleable#AnimationDrawableItem_duration
attr
ref android.R.styleable#AnimationDrawableItem_drawable

Fields Summary
private final AnimationState
mAnimationState
private int
mCurFrame
private boolean
mMutated
Constructors Summary
public AnimationDrawable()


      
        this(null);
    
private AnimationDrawable(AnimationState state)

        AnimationState as = new AnimationState(state, this);
        mAnimationState = as;
        setConstantState(as);
        if (state != null) {
            setFrame(0, true, false);
        }
    
Methods Summary
public voidaddFrame(Drawable frame, int duration)
Add a frame to the animation

param
frame The frame to add
param
duration How long in milliseconds the frame should appear

        mAnimationState.addFrame(frame, duration);
    
public intgetDuration(int i)

return
The duration in milliseconds of the frame at the specified index

        return mAnimationState.mDurations[i];
    
public DrawablegetFrame(int index)

return
The Drawable at the specified frame index

        return mAnimationState.getChildren()[index];
    
public intgetNumberOfFrames()

return
The number of frames in the animation

        return mAnimationState.getChildCount();
    
public voidinflate(android.content.res.Resources r, org.xmlpull.v1.XmlPullParser parser, android.util.AttributeSet attrs)

        
        TypedArray a = r.obtainAttributes(attrs,
                com.android.internal.R.styleable.AnimationDrawable);

        super.inflateWithAttributes(r, parser, a,
                com.android.internal.R.styleable.AnimationDrawable_visible);
        
        mAnimationState.setVariablePadding(a.getBoolean(
                com.android.internal.R.styleable.AnimationDrawable_variablePadding, false));
            
        mAnimationState.mOneShot = a.getBoolean(
                com.android.internal.R.styleable.AnimationDrawable_oneshot, false);
        
        a.recycle();
        
        int type;

        final int innerDepth = parser.getDepth()+1;
        int depth;
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT &&
                ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            if (depth > innerDepth || !parser.getName().equals("item")) {
                continue;
            }
            
            a = r.obtainAttributes(attrs, com.android.internal.R.styleable.AnimationDrawableItem);
            int duration = a.getInt(
                    com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
            if (duration < 0) {
                throw new XmlPullParserException(
                        parser.getPositionDescription()
                        + ": <item> tag requires a 'duration' attribute");
            }
            int drawableRes = a.getResourceId(
                    com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0);
            
            a.recycle();
            
            Drawable dr;
            if (drawableRes != 0) {
                dr = r.getDrawable(drawableRes);
            } else {
                while ((type=parser.next()) == XmlPullParser.TEXT) {
                    // Empty
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new XmlPullParserException(parser.getPositionDescription() +
                            ": <item> tag requires a 'drawable' attribute or child tag" +
                            " defining a drawable");
                }
                dr = Drawable.createFromXmlInner(r, parser, attrs);
            }
            
            mAnimationState.addFrame(dr, duration);
            if (dr != null) {
                dr.setCallback(this);
            }
        }

        setFrame(0, true, false);
    
public booleanisOneShot()

return
True of the animation will play once, false otherwise

        return mAnimationState.mOneShot;
    
public booleanisRunning()

Indicates whether the animation is currently running or not.

return
true if the animation is running, false otherwise

        return mCurFrame > -1;
    
public Drawablemutate()

        if (!mMutated && super.mutate() == this) {
            mAnimationState.mDurations = mAnimationState.mDurations.clone();
            mMutated = true;
        }
        return this;
    
private voidnextFrame(boolean unschedule)

        int next = mCurFrame+1;
        final int N = mAnimationState.getChildCount();
        if (next >= N) {
            next = 0;
        }
        setFrame(next, unschedule, !mAnimationState.mOneShot || next < (N - 1));
    
public voidrun()

This method exists for implementation purpose only and should not be called directly. Invoke {@link #start()} instead.

see
#start()

        nextFrame(false);
    
private voidsetFrame(int frame, boolean unschedule, boolean animate)

        if (frame >= mAnimationState.getChildCount()) {
            return;
        }
        mCurFrame = frame;
        selectDrawable(frame);
        if (unschedule) {
            unscheduleSelf(this);
        }
        if (animate) {
            scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]);
        }
    
public voidsetOneShot(boolean oneShot)
Sets whether the animation should play once or repeat.

param
oneShot Pass true if the animation should only play once

        mAnimationState.mOneShot = oneShot;
    
public booleansetVisible(boolean visible, boolean restart)

        boolean changed = super.setVisible(visible, restart);
        if (visible) {
            if (changed || restart) {
                setFrame(0, true, true);
            }
        } else {
            unscheduleSelf(this);
        }
        return changed;
    
public voidstart()

Starts the animation, looping if necessary. This method has no effect if the animation is running.

see
#isRunning()
see
#stop()

        if (!isRunning()) {
            run();
        }
    
public voidstop()

Stops the animation. This method has no effect if the animation is not running.

see
#isRunning()
see
#start()

        if (isRunning()) {
            unscheduleSelf(this);
        }
    
public voidunscheduleSelf(java.lang.Runnable what)

        mCurFrame = -1;
        super.unscheduleSelf(what);