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
4370e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * {@code &lt;animation-list&gt;} element and a series of nested
4470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette * {@code &lt;item&gt;} 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>
108100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * When the drawable becomes invisible, it will pause its animation. A
109100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * subsequent change to visible with <code>restart</code> set to true will
110100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * restart the animation from the first frame. If <code>restart</code> is
111100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * false, the animation will resume from the most recent frame.
112100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     *
113100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @param visible true if visible, false otherwise
114100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @param restart when visible, true to force the animation to restart
115100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     *                from the first frame
116100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     * @return true if the new visibility is different than its previous state
117100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette     */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setVisible(boolean visible, boolean restart) {
12097fb0aa5090858705b66bfc4c05e7530c5d3d6b1Alan Viverette        final boolean changed = super.setVisible(visible, restart);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
122100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette            if (restart || changed) {
12356ef127df75164243a21df10771e7c77c8ef2e24Doris Liu                boolean startFromZero = restart || !mRunning ||
124030435773dc5413a690d460e97fd681740cd32efChet Haase                        mCurFrame >= mAnimationState.getChildCount();
125030435773dc5413a690d460e97fd681740cd32efChet Haase                setFrame(startFromZero ? 0 : mCurFrame, true, mAnimating);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return changed;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Starts the animation, looping if necessary. This method has no effect
13570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * if the animation is running.
13670e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * <p>
13770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * <strong>Note:</strong> Do not call this in the
13870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * {@link android.app.Activity#onCreate} method of your activity, because
13970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * the {@link AnimationDrawable} is not yet fully attached to the window.
14070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * If you want to play the animation immediately without requiring
14170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * interaction, then you might want to call it from the
14270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * {@link android.app.Activity#onWindowFocusChanged} method in your
14370e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * activity, which will get called when Android brings your window into
14470e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * focus.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isRunning()
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #stop()
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
149b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void start() {
151100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = true;
152100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isRunning()) {
154c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu            // Start from 0th frame.
155c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu            setFrame(0, false, mAnimationState.getChildCount() > 1
156c7741d467b37351ab13f75592fc7400d0c2ba6d7Doris Liu                    || !mAnimationState.mOneShot);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Stops the animation. This method has no effect if the animation is not
16270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * running.
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isRunning()
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #start()
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
167b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stop() {
169100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = false;
170100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isRunning()) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Indicates whether the animation is currently running or not.
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the animation is running, false otherwise
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
181b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isRunning() {
183100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        return mRunning;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * This method exists for implementation purpose only and should not be
18870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * called directly. Invoke {@link #start()} instead.
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #start()
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
192b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void run() {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nextFrame(false);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unscheduleSelf(Runnable what) {
19956ef127df75164243a21df10771e7c77c8ef2e24Doris Liu        mCurFrame = 0;
200100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mRunning = false;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.unscheduleSelf(what);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of frames in the animation
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumberOfFrames() {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.getChildCount();
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
210b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The Drawable at the specified frame index
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getFrame(int index) {
21572146433322588c1116ee06c27ac758ad09d869cAlan Viverette        return mAnimationState.getChild(index);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
217b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
219b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     * @return The duration in milliseconds of the frame at the
22070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     *         specified index
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDuration(int i) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.mDurations[i];
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
225b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True of the animation will play once, false otherwise
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isOneShot() {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationState.mOneShot;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
232b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the animation should play once or repeat.
235b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     *
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param oneShot Pass true if the animation should only play once
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOneShot(boolean oneShot) {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationState.mOneShot = oneShot;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
241b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
24370e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette     * Adds a frame to the animation
244b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette     *
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param frame The frame to add
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param duration How long in milliseconds the frame should appear
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
24870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette    public void addFrame(@NonNull Drawable frame, int duration) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationState.addFrame(frame, duration);
25056ef127df75164243a21df10771e7c77c8ef2e24Doris Liu        if (!mRunning) {
251f5534a0785db9dfa239d8b6c20b011993742d534Chet Haase            setFrame(0, true, false);
252f5534a0785db9dfa239d8b6c20b011993742d534Chet Haase        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
254b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void nextFrame(boolean unschedule) {
25670e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        int nextFrame = mCurFrame + 1;
25770e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        final int numFrames = mAnimationState.getChildCount();
25870e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        final boolean isLastFrame = mAnimationState.mOneShot && nextFrame >= (numFrames - 1);
25970e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette
26070e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        // Loop if necessary. One-shot animations should never hit this case.
26170e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        if (!mAnimationState.mOneShot && nextFrame >= numFrames) {
26270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette            nextFrame = 0;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
264100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette
26570e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        setFrame(nextFrame, unschedule, !isLastFrame);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setFrame(int frame, boolean unschedule, boolean animate) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (frame >= mAnimationState.getChildCount()) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
272100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette        mAnimating = animate;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurFrame = frame;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        selectDrawable(frame);
275180979f76b0c99cd7053a44692f6408721b74bceJohn Spurlock        if (unschedule || animate) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unscheduleSelf(this);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (animate) {
279180979f76b0c99cd7053a44692f6408721b74bceJohn Spurlock            // Unscheduling may have clobbered these values; restore them
280f7917e656b94ec2adfc3fa826e093665d39748d2Chet Haase            mCurFrame = frame;
281100a2d1fc67d79d19afa0c00830350a5d4ab0c59Alan Viverette            mRunning = true;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
28752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
289d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
290d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
291d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        updateStateFromTypedArray(a);
292d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        a.recycle();
293b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
294d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        inflateChildElements(r, parser, attrs, theme);
295b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
296d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        setFrame(0, true, false);
297d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    }
298b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
299d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
300d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int innerDepth = parser.getDepth()+1;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
305d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
306d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth || !parser.getName().equals("item")) {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
314b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3152d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            final TypedArray a = obtainAttributes(r, theme, attrs,
3162d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette                    R.styleable.AnimationDrawableItem);
317d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
318d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette            final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration < 0) {
320d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                throw new XmlPullParserException(parser.getPositionDescription()
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": <item> tag requires a 'duration' attribute");
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
323d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
3242d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            Drawable dr = a.getDrawable(R.styleable.AnimationDrawableItem_drawable);
325b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a.recycle();
327b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3282d91f63ec20c4b06e87c80451a656462eceba17fAlan Viverette            if (dr == null) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((type=parser.next()) == XmlPullParser.TEXT) {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Empty
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type != XmlPullParser.START_TAG) {
333d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                    throw new XmlPullParserException(parser.getPositionDescription()
334d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                            + ": <item> tag requires a 'drawable' attribute or child tag"
335d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                            + " defining a drawable");
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3376dbe51b50e82057af4d29882889444d22ac19c9cAlan Viverette                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
339b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAnimationState.addFrame(dr, duration);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dr != null) {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dr.setCallback(this);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
345d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
347d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette    private void updateStateFromTypedArray(TypedArray a) {
348d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        mAnimationState.mVariablePadding = a.getBoolean(
349d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);
350d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
351d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        mAnimationState.mOneShot = a.getBoolean(
352d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
35670e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette    @NonNull
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
3598dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            mAnimationState.mutate();
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3658dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    @Override
3668dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    AnimationState cloneConstantState() {
3678dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        return new AnimationState(mAnimationState, this, null);
3688dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    }
3698dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
370727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
371727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
372727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
373727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
374727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
375727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
376727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
377727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static class AnimationState extends DrawableContainerState {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int[] mDurations;
380d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        private boolean mOneShot = false;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38270e68e0ff17f3d47f382b6ac0e6a7eb49be17965Alan Viverette        AnimationState(AnimationState orig, AnimationDrawable owner, Resources res) {
383c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            super(orig, owner, res);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orig != null) {
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDurations = orig.mDurations;
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOneShot = orig.mOneShot;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
38972146433322588c1116ee06c27ac758ad09d869cAlan Viverette                mDurations = new int[getCapacity()];
3900b9ab9749aec297aa03c3fde6d5552c9f212ddbfAlan Viverette                mOneShot = false;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3948dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        private void mutate() {
3958dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            mDurations = mDurations.clone();
3968dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        }
3978dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
400c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimationDrawable(this, null);
401c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
402c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
403c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
404c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
405c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimationDrawable(this, res);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void addFrame(Drawable dr, int dur) {
409b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Do not combine the following. The array index must be evaluated before
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the array is accessed because super.addChild(dr) has a side effect on mDurations.
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = super.addChild(dr);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDurations[pos] = dur;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void growArray(int oldSize, int newSize) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.growArray(oldSize, newSize);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] newDurations = new int[newSize];
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.arraycopy(mDurations, 0, newDurations, 0, oldSize);
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDurations = newDurations;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4245ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    @Override
4255ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    protected void setConstantState(@NonNull DrawableContainerState state) {
4265ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        super.setConstantState(state);
4275ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette
4285ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        if (state instanceof AnimationState) {
4295ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            mAnimationState = (AnimationState) state;
4305ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        }
4315ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette    }
4325ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette
433c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private AnimationDrawable(AnimationState state, Resources res) {
4345ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette        final AnimationState as = new AnimationState(state, this, res);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setConstantState(as);
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state != null) {
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setFrame(0, true, false);
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
442