alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (AnimationDrawable.java)

This example Android source code file (AnimationDrawable.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, animatable, animationdrawable, animationstate, attributeset, content, drawable, drawablecontainer, drawablecontainerstate, io, ioexception, os, override, resources, runnable, typedarray, util, utilities, xmlpullparserexception

The AnimationDrawable.java Android example source code

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics.drawable;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.SystemClock;
import android.util.AttributeSet;

/**
 * 
 * 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.
 * <p>
 * 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.
 * <p>
 * An AnimationDrawable defined in XML consists of a single <code><animation-list> element,
 * and a series of nested <code><item> tags. Each item defines a frame of the animation.
 * See the example below.
 * </p>
 * <p>spin_animation.xml file in res/drawable/ folder:

* <pre><!-- 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></pre> * * <p>Here is the code to load and play this animation.

* <pre> * // 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() * </pre> * * @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 */ public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable { private final AnimationState mAnimationState; private int mCurFrame = -1; private boolean mMutated; public AnimationDrawable() { this(null, null); } @Override 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; } /** * <p>Starts the animation, looping if necessary. This method has no effect * if the animation is running.</p> * * @see #isRunning() * @see #stop() */ public void start() { if (!isRunning()) { run(); } } /** * <p>Stops the animation. This method has no effect if the animation is * not running.</p> * * @see #isRunning() * @see #start() */ public void stop() { if (isRunning()) { unscheduleSelf(this); } } /** * <p>Indicates whether the animation is currently running or not.

* * @return true if the animation is running, false otherwise */ public boolean isRunning() { return mCurFrame > -1; } /** * <p>This method exists for implementation purpose only and should not be * called directly. Invoke {@link #start()} instead.</p> * * @see #start() */ public void run() { nextFrame(false); } @Override public void unscheduleSelf(Runnable what) { mCurFrame = -1; super.unscheduleSelf(what); } /** * @return The number of frames in the animation */ public int getNumberOfFrames() { return mAnimationState.getChildCount(); } /** * @return The Drawable at the specified frame index */ public Drawable getFrame(int index) { return mAnimationState.getChildren()[index]; } /** * @return The duration in milliseconds of the frame at the * specified index */ public int getDuration(int i) { return mAnimationState.mDurations[i]; } /** * @return True of the animation will play once, false otherwise */ public boolean isOneShot() { return mAnimationState.mOneShot; } /** * Sets whether the animation should play once or repeat. * * @param oneShot Pass true if the animation should only play once */ public void setOneShot(boolean oneShot) { mAnimationState.mOneShot = oneShot; } /** * Add a frame to the animation * * @param frame The frame to add * @param duration How long in milliseconds the frame should appear */ public void addFrame(Drawable frame, int duration) { mAnimationState.addFrame(frame, duration); } 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)); } 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]); } } @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException { 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); } @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { mAnimationState.mDurations = mAnimationState.mDurations.clone(); mMutated = true; } return this; } private final static class AnimationState extends DrawableContainerState { private int[] mDurations; private boolean mOneShot; AnimationState(AnimationState orig, AnimationDrawable owner, Resources res) { super(orig, owner, res); if (orig != null) { mDurations = orig.mDurations; mOneShot = orig.mOneShot; } else { mDurations = new int[getChildren().length]; mOneShot = true; } } @Override public Drawable newDrawable() { return new AnimationDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { return new AnimationDrawable(this, res); } public void addFrame(Drawable dr, int dur) { // Do not combine the following. The array index must be evaluated before // the array is accessed because super.addChild(dr) has a side effect on mDurations. int pos = super.addChild(dr); mDurations[pos] = dur; } @Override public void growArray(int oldSize, int newSize) { super.growArray(oldSize, newSize); int[] newDurations = new int[newSize]; System.arraycopy(mDurations, 0, newDurations, 0, oldSize); mDurations = newDurations; } } private AnimationDrawable(AnimationState state, Resources res) { AnimationState as = new AnimationState(state, this, res); mAnimationState = as; setConstantState(as); if (state != null) { setFrame(0, true, false); } } }

Other Android examples (source code examples)

Here is a short list of links related to this Android AnimationDrawable.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.