AnimationDrawablepublic class AnimationDrawable extends DrawableContainer implements RunnableAn 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()
|
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 void | addFrame(Drawable frame, int duration)Add a frame to the animation
mAnimationState.addFrame(frame, duration);
| public int | getDuration(int i)
return mAnimationState.mDurations[i];
| public Drawable | getFrame(int index)
return mAnimationState.getChildren()[index];
| public int | getNumberOfFrames()
return mAnimationState.getChildCount();
| public void | inflate(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 boolean | isOneShot()
return mAnimationState.mOneShot;
| public boolean | isRunning()Indicates whether the animation is currently running or not.
return mCurFrame > -1;
| public Drawable | mutate()
if (!mMutated && super.mutate() == this) {
mAnimationState.mDurations = mAnimationState.mDurations.clone();
mMutated = true;
}
return this;
| private void | nextFrame(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 void | run()This method exists for implementation purpose only and should not be
called directly. Invoke {@link #start()} instead.
nextFrame(false);
| private void | setFrame(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 void | setOneShot(boolean oneShot)Sets whether the animation should play once or repeat.
mAnimationState.mOneShot = oneShot;
| public boolean | setVisible(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 void | start()Starts the animation, looping if necessary. This method has no effect
if the animation is running.
if (!isRunning()) {
run();
}
| public void | stop()Stops the animation. This method has no effect if the animation is
not running.
if (isRunning()) {
unscheduleSelf(this);
}
| public void | unscheduleSelf(java.lang.Runnable what)
mCurFrame = -1;
super.unscheduleSelf(what);
|
|