19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viveretteimport com.android.internal.R;
20d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
265ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viveretteimport android.annotation.NonNull;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
2952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * An object used to create frame-by-frame animations, defined by a series of
3570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * Drawable objects, which can be used as a View object's background.
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
3770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * The simplest way to create a frame-by-frame animation is to define the
3870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * animation in an XML file, placed in the res/drawable/ folder, and set it as
3970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * the background to a View object. Then, call {@link #start()} to run the
4070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * animation.
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
4270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * An AnimationDrawable defined in XML consists of a single
4371fbb81b14958b80fe55738607740c6630e4e9daNeil Fuller * {@code <animation-list>} element and a series of nested
4471fbb81b14958b80fe55738607740c6630e4e9daNeil Fuller * {@code <item>} tags. Each item defines a frame of the animation. See
4570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * the example below.
4670e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * <p>
4770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * spin_animation.xml file in res/drawable/ folder:
4870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * <pre>
4970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * &lt;!-- Animation frames are wheel0.png through wheel5.png
5070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette *     files inside the res/drawable/ folder --&gt;
51f7917e656b94ec2adfc3fa826e093665d39748d2Chet Haase * &lt;animation-list android:id=&quot;@+id/selected&quot; android:oneshot=&quot;false&quot;&gt;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel0&quot; android:duration=&quot;50&quot; /&gt;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel1&quot; android:duration=&quot;50&quot; /&gt;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel2&quot; android:duration=&quot;50&quot; /&gt;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel3&quot; android:duration=&quot;50&quot; /&gt;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel4&quot; android:duration=&quot;50&quot; /&gt;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    &lt;item android:drawable=&quot;@drawable/wheel5&quot; android:duration=&quot;50&quot; /&gt;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;/animation-list&gt;</pre>
5970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * <p>
6070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * Here is the code to load and play this animation.
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // Load the ImageView that will host the animation and
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // set its background to our AnimationDrawable XML resource.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * img.setBackgroundResource(R.drawable.spin_animation);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // Get the background, which has been compiled to an AnimationDrawable object.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // Start the animation (looped playback by default).
71f5534a0785db9dfa239d8b6c20b011993742d534Chet Haase * frameAnimation.start();
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
733aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
743aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
753aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
763aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about animating with {@code AnimationDrawable}, read the
773aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/graphics/drawable-animation.html">Drawable Animation</a>
783aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * developer guide.</p>
793aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#AnimationDrawable_visible
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#AnimationDrawable_variablePadding
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#AnimationDrawable_oneshot
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#AnimationDrawableItem_duration
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#AnimationDrawableItem_drawable
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
87b5537c452271634b6ff3981b0624fa65384abd5bRomain Guypublic class AnimationDrawable extends DrawableContainer implements Runnable, Animatable {
885ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    private AnimationState mAnimationState;
89100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
9056ef127df75164243a21df10771e7c77c8ef2e24Doris Liu    /** The current frame, ranging from 0 to {@link #mAnimationState#getChildCount() - 1} */
9156ef127df75164243a21df10771e7c77c8ef2e24Doris Liu    private int mCurFrame = 0;
92100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
93100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette    /** Whether the drawable has an animation callback posted. */
94100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette    private boolean mRunning;
95100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
96100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette    /** Whether the drawable should animate when visible. */
97180979f76b0c99cd7053a44692f6408721b74bceJohn Spurlock    private boolean mAnimating;
98100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMutated;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AnimationDrawable() {
102c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(null, null);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette    /**
106100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * Sets whether this AnimationDrawable is visible.
107100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * <p>
108084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * When the drawable becomes invisible, it will pause its animation. A subsequent change to
109084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * visible with <code>restart</code> set to true will restart the animation from the
110084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * first frame. If <code>restart</code> is false, the drawable will resume from the most recent
111084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * frame. If the drawable has already reached the last frame, it will then loop back to the
112084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * first frame, unless it's a one shot drawable (set through {@link #setOneShot(boolean)}),
113084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * in which case, it will stay on the last frame.
114100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     *
115100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @param visible true if visible, false otherwise
116100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @param restart when visible, true to force the animation to restart
117100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     *                from the first frame
118100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @return true if the new visibility is different than its previous state
119100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setVisible(boolean visible, boolean restart) {
12297fb0aa5090858705b66bfc4c05e7530c5d3d6b1Alan Viverette        final boolean changed = super.setVisible(visible, restart);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
124100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette            if (restart || changed) {
125084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu                boolean startFromZero = restart || (!mRunning && !mAnimationState.mOneShot) ||
126030435773dc5413a690d460e97fd681740cd32efChet Haase                        mCurFrame >= mAnimationState.getChildCount();
127030435773dc5413a690d460e97fd681740cd32efChet Haase                setFrame(startFromZero ? 0 : mCurFrame, true, mAnimating);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return changed;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
136084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * Starts the animation from the first frame, looping if necessary. This method has no effect
13770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * if the animation is running.
13870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * <p>
13970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * <strong>Note:</strong> Do not call this in the
14070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * {@link android.app.Activity#onCreate} method of your activity, because
14170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * the {@link AnimationDrawable} is not yet fully attached to the window.
14270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * If you want to play the animation immediately without requiring
14370e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * interaction, then you might want to call it from the
14470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * {@link android.app.Activity#onWindowFocusChanged} method in your
14570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * activity, which will get called when Android brings your window into
14670e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * focus.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isRunning()
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #stop()
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
151b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void start() {
153100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = true;
154100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isRunning()) {
156c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu            // Start from 0th frame.
157c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu            setFrame(0, false, mAnimationState.getChildCount() > 1
158c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu                    || !mAnimationState.mOneShot);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
163084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu     * Stops the animation at the current frame. This method has no effect if the animation is not
16470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * running.
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isRunning()
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #start()
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
169b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stop() {
171100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = false;
172100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isRunning()) {
174084938f2a1b8224bf9ada8a4bc3b48b5cf9275e9Doris Liu            mCurFrame = 0;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Indicates whether the animation is currently running or not.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the animation is running, false otherwise
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
184b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isRunning() {
186100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        return mRunning;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * This method exists for implementation purpose only and should not be
19170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * called directly. Invoke {@link #start()} instead.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #start()
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
195b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void run() {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nextFrame(false);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unscheduleSelf(Runnable what) {
202100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mRunning = false;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.unscheduleSelf(what);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of frames in the animation
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumberOfFrames() {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.getChildCount();
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
212b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The Drawable at the specified frame index
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getFrame(int index) {
21772146433322588c1116ee06c27ac758ad09d869cAlan Viverette        return mAnimationState.getChild(index);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
219b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
221b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     * @return The duration in milliseconds of the frame at the
22270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     *         specified index
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDuration(int i) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.mDurations[i];
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
227b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True of the animation will play once, false otherwise
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isOneShot() {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.mOneShot;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
234b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the animation should play once or repeat.
237b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     *
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param oneShot Pass true if the animation should only play once
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOneShot(boolean oneShot) {
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationState.mOneShot = oneShot;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
243b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
24570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Adds a frame to the animation
246b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     *
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param frame The frame to add
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param duration How long in milliseconds the frame should appear
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette    public void addFrame(@NonNull Drawable frame, int duration) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationState.addFrame(frame, duration);
25256ef127df75164243a21df10771e7c77c8ef2e24Doris Liu        if (!mRunning) {
253f5534a0785db9dfa239d8b6c20b011993742d534Chet Haase            setFrame(0, true, false);
254f5534a0785db9dfa239d8b6c20b011993742d534Chet Haase        }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
256b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void nextFrame(boolean unschedule) {
25870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        int nextFrame = mCurFrame + 1;
25970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        final int numFrames = mAnimationState.getChildCount();
26070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        final boolean isLastFrame = mAnimationState.mOneShot && nextFrame >= (numFrames - 1);
26170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette
26270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        // Loop if necessary. One-shot animations should never hit this case.
26370e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        if (!mAnimationState.mOneShot && nextFrame >= numFrames) {
26470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette            nextFrame = 0;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
266100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
26770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        setFrame(nextFrame, unschedule, !isLastFrame);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setFrame(int frame, boolean unschedule, boolean animate) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (frame >= mAnimationState.getChildCount()) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
274100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = animate;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurFrame = frame;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        selectDrawable(frame);
277180979f76b0c99cd7053a44692f6408721b74bceJohn Spurlock        if (unschedule || animate) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (animate) {
281180979f76b0c99cd7053a44692f6408721b74bceJohn Spurlock            // Unscheduling may have clobbered these values; restore them
282f7917e656b94ec2adfc3fa826e093665d39748d2Chet Haase            mCurFrame = frame;
283100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette            mRunning = true;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
28952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
291d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
292d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
293d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        updateStateFromTypedArray(a);
294f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        updateDensity(r);
295d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        a.recycle();
296b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
297d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        inflateChildElements(r, parser, attrs, theme);
298b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
299d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        setFrame(0, true, false);
300d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    }
301b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
302d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
303d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int innerDepth = parser.getDepth()+1;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
308d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
309d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth || !parser.getName().equals("item")) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
317b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3182d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            final TypedArray a = obtainAttributes(r, theme, attrs,
3192d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette                    R.styleable.AnimationDrawableItem);
320d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
321d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette            final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration < 0) {
323d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                throw new XmlPullParserException(parser.getPositionDescription()
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": <item> tag requires a 'duration' attribute");
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
326d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
3272d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            Drawable dr = a.getDrawable(R.styleable.AnimationDrawableItem_drawable);
328b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a.recycle();
330b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3312d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            if (dr == null) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type=parser.next()) == XmlPullParser.TEXT) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
336d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                    throw new XmlPullParserException(parser.getPositionDescription()
337d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                            + ": <item> tag requires a 'drawable' attribute or child tag"
338d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                            + " defining a drawable");
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3406dbe51b50e82057af4d29882889444d22ac19c9cAlan Viverette                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
342b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAnimationState.addFrame(dr, duration);
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dr != null) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dr.setCallback(this);
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
348d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
350d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    private void updateStateFromTypedArray(TypedArray a) {
351d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        mAnimationState.mVariablePadding = a.getBoolean(
352d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);
353d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
354d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        mAnimationState.mOneShot = a.getBoolean(
355d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
35970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette    @NonNull
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
3628dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            mAnimationState.mutate();
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3688dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    @Override
3698dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    AnimationState cloneConstantState() {
3708dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        return new AnimationState(mAnimationState, this, null);
3718dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    }
3728dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
373727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
374727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
375727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
376727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
377727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
378727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
379727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
380727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static class AnimationState extends DrawableContainerState {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int[] mDurations;
383d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        private boolean mOneShot = false;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        AnimationState(AnimationState orig, AnimationDrawable owner, Resources res) {
386c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            super(orig, owner, res);
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orig != null) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDurations = orig.mDurations;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOneShot = orig.mOneShot;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
39272146433322588c1116ee06c27ac758ad09d869cAlan Viverette                mDurations = new int[getCapacity()];
3930b9ab9749aec297aa03c3fde6d5552c9f212ddbfAlan Viverette                mOneShot = false;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3978dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        private void mutate() {
3988dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            mDurations = mDurations.clone();
3998dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        }
4008dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
403c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimationDrawable(this, null);
404c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
405c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
406c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
407c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
408c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimationDrawable(this, res);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void addFrame(Drawable dr, int dur) {
412b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Do not combine the following. The array index must be evaluated before
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the array is accessed because super.addChild(dr) has a side effect on mDurations.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = super.addChild(dr);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDurations[pos] = dur;
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void growArray(int oldSize, int newSize) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.growArray(oldSize, newSize);
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] newDurations = new int[newSize];
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.arraycopy(mDurations, 0, newDurations, 0, oldSize);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDurations = newDurations;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4275ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    @Override
4285ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    protected void setConstantState(@NonNull DrawableContainerState state) {
4295ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        super.setConstantState(state);
4305ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette
4315ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        if (state instanceof AnimationState) {
4325ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            mAnimationState = (AnimationState) state;
4335ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        }
4345ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    }
4355ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette
436c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private AnimationDrawable(AnimationState state, Resources res) {
4375ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        final AnimationState as = new AnimationState(state, this, res);
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setConstantState(as);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state != null) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setFrame(0, true, false);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
445