Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.animation;
     18 
     19 import java.util.ArrayList;
     20 
     21 /**
     22  * This is the superclass for classes which provide basic support for animations which can be
     23  * started, ended, and have <code>AnimatorListeners</code> added to them.
     24  */
     25 public abstract class Animator implements Cloneable {
     26 
     27     /**
     28      * The set of listeners to be sent events through the life of an animation.
     29      */
     30     ArrayList<AnimatorListener> mListeners = null;
     31 
     32     /**
     33      * The set of listeners to be sent pause/resume events through the life
     34      * of an animation.
     35      */
     36     ArrayList<AnimatorPauseListener> mPauseListeners = null;
     37 
     38     /**
     39      * Whether this animator is currently in a paused state.
     40      */
     41     boolean mPaused = false;
     42 
     43     /**
     44      * Starts this animation. If the animation has a nonzero startDelay, the animation will start
     45      * running after that delay elapses. A non-delayed animation will have its initial
     46      * value(s) set immediately, followed by calls to
     47      * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator.
     48      *
     49      * <p>The animation started by calling this method will be run on the thread that called
     50      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
     51      * this is not the case). Also, if the animation will animate
     52      * properties of objects in the view hierarchy, then the calling thread should be the UI
     53      * thread for that view hierarchy.</p>
     54      *
     55      */
     56     public void start() {
     57     }
     58 
     59     /**
     60      * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
     61      * stop in its tracks, sending an
     62      * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
     63      * its listeners, followed by an
     64      * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
     65      *
     66      * <p>This method must be called on the thread that is running the animation.</p>
     67      */
     68     public void cancel() {
     69     }
     70 
     71     /**
     72      * Ends the animation. This causes the animation to assign the end value of the property being
     73      * animated, then calling the
     74      * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
     75      * its listeners.
     76      *
     77      * <p>This method must be called on the thread that is running the animation.</p>
     78      */
     79     public void end() {
     80     }
     81 
     82     /**
     83      * Pauses a running animation. This method should only be called on the same thread on
     84      * which the animation was started. If the animation has not yet been {@link
     85      * #isStarted() started} or has since ended, then the call is ignored. Paused
     86      * animations can be resumed by calling {@link #resume()}.
     87      *
     88      * @see #resume()
     89      * @see #isPaused()
     90      * @see AnimatorPauseListener
     91      */
     92     public void pause() {
     93         if (isStarted() && !mPaused) {
     94             mPaused = true;
     95             if (mPauseListeners != null) {
     96                 ArrayList<AnimatorPauseListener> tmpListeners =
     97                         (ArrayList<AnimatorPauseListener>) mPauseListeners.clone();
     98                 int numListeners = tmpListeners.size();
     99                 for (int i = 0; i < numListeners; ++i) {
    100                     tmpListeners.get(i).onAnimationPause(this);
    101                 }
    102             }
    103         }
    104     }
    105 
    106     /**
    107      * Resumes a paused animation, causing the animator to pick up where it left off
    108      * when it was paused. This method should only be called on the same thread on
    109      * which the animation was started. Calls to resume() on an animator that is
    110      * not currently paused will be ignored.
    111      *
    112      * @see #pause()
    113      * @see #isPaused()
    114      * @see AnimatorPauseListener
    115      */
    116     public void resume() {
    117         if (mPaused) {
    118             mPaused = false;
    119             if (mPauseListeners != null) {
    120                 ArrayList<AnimatorPauseListener> tmpListeners =
    121                         (ArrayList<AnimatorPauseListener>) mPauseListeners.clone();
    122                 int numListeners = tmpListeners.size();
    123                 for (int i = 0; i < numListeners; ++i) {
    124                     tmpListeners.get(i).onAnimationResume(this);
    125                 }
    126             }
    127         }
    128     }
    129 
    130     /**
    131      * Returns whether this animator is currently in a paused state.
    132      *
    133      * @return True if the animator is currently paused, false otherwise.
    134      *
    135      * @see #pause()
    136      * @see #resume()
    137      */
    138     public boolean isPaused() {
    139         return mPaused;
    140     }
    141 
    142     /**
    143      * The amount of time, in milliseconds, to delay processing the animation
    144      * after {@link #start()} is called.
    145      *
    146      * @return the number of milliseconds to delay running the animation
    147      */
    148     public abstract long getStartDelay();
    149 
    150     /**
    151      * The amount of time, in milliseconds, to delay processing the animation
    152      * after {@link #start()} is called.
    153 
    154      * @param startDelay The amount of the delay, in milliseconds
    155      */
    156     public abstract void setStartDelay(long startDelay);
    157 
    158     /**
    159      * Sets the duration of the animation.
    160      *
    161      * @param duration The length of the animation, in milliseconds.
    162      */
    163     public abstract Animator setDuration(long duration);
    164 
    165     /**
    166      * Gets the duration of the animation.
    167      *
    168      * @return The length of the animation, in milliseconds.
    169      */
    170     public abstract long getDuration();
    171 
    172     /**
    173      * The time interpolator used in calculating the elapsed fraction of the
    174      * animation. The interpolator determines whether the animation runs with
    175      * linear or non-linear motion, such as acceleration and deceleration. The
    176      * default value is {@link android.view.animation.AccelerateDecelerateInterpolator}.
    177      *
    178      * @param value the interpolator to be used by this animation
    179      */
    180     public abstract void setInterpolator(TimeInterpolator value);
    181 
    182     /**
    183      * Returns the timing interpolator that this animation uses.
    184      *
    185      * @return The timing interpolator for this animation.
    186      */
    187     public TimeInterpolator getInterpolator() {
    188         return null;
    189     }
    190 
    191     /**
    192      * Returns whether this Animator is currently running (having been started and gone past any
    193      * initial startDelay period and not yet ended).
    194      *
    195      * @return Whether the Animator is running.
    196      */
    197     public abstract boolean isRunning();
    198 
    199     /**
    200      * Returns whether this Animator has been started and not yet ended. This state is a superset
    201      * of the state of {@link #isRunning()}, because an Animator with a nonzero
    202      * {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during the
    203      * delay phase, whereas {@link #isRunning()} will return true only after the delay phase
    204      * is complete.
    205      *
    206      * @return Whether the Animator has been started and not yet ended.
    207      */
    208     public boolean isStarted() {
    209         // Default method returns value for isRunning(). Subclasses should override to return a
    210         // real value.
    211         return isRunning();
    212     }
    213 
    214     /**
    215      * Adds a listener to the set of listeners that are sent events through the life of an
    216      * animation, such as start, repeat, and end.
    217      *
    218      * @param listener the listener to be added to the current set of listeners for this animation.
    219      */
    220     public void addListener(AnimatorListener listener) {
    221         if (mListeners == null) {
    222             mListeners = new ArrayList<AnimatorListener>();
    223         }
    224         mListeners.add(listener);
    225     }
    226 
    227     /**
    228      * Removes a listener from the set listening to this animation.
    229      *
    230      * @param listener the listener to be removed from the current set of listeners for this
    231      *                 animation.
    232      */
    233     public void removeListener(AnimatorListener listener) {
    234         if (mListeners == null) {
    235             return;
    236         }
    237         mListeners.remove(listener);
    238         if (mListeners.size() == 0) {
    239             mListeners = null;
    240         }
    241     }
    242 
    243     /**
    244      * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
    245      * listening for events on this <code>Animator</code> object.
    246      *
    247      * @return ArrayList<AnimatorListener> The set of listeners.
    248      */
    249     public ArrayList<AnimatorListener> getListeners() {
    250         return mListeners;
    251     }
    252 
    253     /**
    254      * Adds a pause listener to this animator.
    255      *
    256      * @param listener the listener to be added to the current set of pause listeners
    257      * for this animation.
    258      */
    259     public void addPauseListener(AnimatorPauseListener listener) {
    260         if (mPauseListeners == null) {
    261             mPauseListeners = new ArrayList<AnimatorPauseListener>();
    262         }
    263         mPauseListeners.add(listener);
    264     }
    265 
    266     /**
    267      * Removes a pause listener from the set listening to this animation.
    268      *
    269      * @param listener the listener to be removed from the current set of pause
    270      * listeners for this animation.
    271      */
    272     public void removePauseListener(AnimatorPauseListener listener) {
    273         if (mPauseListeners == null) {
    274             return;
    275         }
    276         mPauseListeners.remove(listener);
    277         if (mPauseListeners.size() == 0) {
    278             mPauseListeners = null;
    279         }
    280     }
    281 
    282     /**
    283      * Removes all {@link #addListener(android.animation.Animator.AnimatorListener) listeners}
    284      * and {@link #addPauseListener(android.animation.Animator.AnimatorPauseListener)
    285      * pauseListeners} from this object.
    286      */
    287     public void removeAllListeners() {
    288         if (mListeners != null) {
    289             mListeners.clear();
    290             mListeners = null;
    291         }
    292         if (mPauseListeners != null) {
    293             mPauseListeners.clear();
    294             mPauseListeners = null;
    295         }
    296     }
    297 
    298     @Override
    299     public Animator clone() {
    300         try {
    301             final Animator anim = (Animator) super.clone();
    302             if (mListeners != null) {
    303                 ArrayList<AnimatorListener> oldListeners = mListeners;
    304                 anim.mListeners = new ArrayList<AnimatorListener>();
    305                 int numListeners = oldListeners.size();
    306                 for (int i = 0; i < numListeners; ++i) {
    307                     anim.mListeners.add(oldListeners.get(i));
    308                 }
    309             }
    310             if (mPauseListeners != null) {
    311                 ArrayList<AnimatorPauseListener> oldListeners = mPauseListeners;
    312                 anim.mPauseListeners = new ArrayList<AnimatorPauseListener>();
    313                 int numListeners = oldListeners.size();
    314                 for (int i = 0; i < numListeners; ++i) {
    315                     anim.mPauseListeners.add(oldListeners.get(i));
    316                 }
    317             }
    318             return anim;
    319         } catch (CloneNotSupportedException e) {
    320            throw new AssertionError();
    321         }
    322     }
    323 
    324     /**
    325      * This method tells the object to use appropriate information to extract
    326      * starting values for the animation. For example, a AnimatorSet object will pass
    327      * this call to its child objects to tell them to set up the values. A
    328      * ObjectAnimator object will use the information it has about its target object
    329      * and PropertyValuesHolder objects to get the start values for its properties.
    330      * A ValueAnimator object will ignore the request since it does not have enough
    331      * information (such as a target object) to gather these values.
    332      */
    333     public void setupStartValues() {
    334     }
    335 
    336     /**
    337      * This method tells the object to use appropriate information to extract
    338      * ending values for the animation. For example, a AnimatorSet object will pass
    339      * this call to its child objects to tell them to set up the values. A
    340      * ObjectAnimator object will use the information it has about its target object
    341      * and PropertyValuesHolder objects to get the start values for its properties.
    342      * A ValueAnimator object will ignore the request since it does not have enough
    343      * information (such as a target object) to gather these values.
    344      */
    345     public void setupEndValues() {
    346     }
    347 
    348     /**
    349      * Sets the target object whose property will be animated by this animation. Not all subclasses
    350      * operate on target objects (for example, {@link ValueAnimator}, but this method
    351      * is on the superclass for the convenience of dealing generically with those subclasses
    352      * that do handle targets.
    353      *
    354      * @param target The object being animated
    355      */
    356     public void setTarget(Object target) {
    357     }
    358 
    359     /**
    360      * <p>An animation listener receives notifications from an animation.
    361      * Notifications indicate animation related events, such as the end or the
    362      * repetition of the animation.</p>
    363      */
    364     public static interface AnimatorListener {
    365         /**
    366          * <p>Notifies the start of the animation.</p>
    367          *
    368          * @param animation The started animation.
    369          */
    370         void onAnimationStart(Animator animation);
    371 
    372         /**
    373          * <p>Notifies the end of the animation. This callback is not invoked
    374          * for animations with repeat count set to INFINITE.</p>
    375          *
    376          * @param animation The animation which reached its end.
    377          */
    378         void onAnimationEnd(Animator animation);
    379 
    380         /**
    381          * <p>Notifies the cancellation of the animation. This callback is not invoked
    382          * for animations with repeat count set to INFINITE.</p>
    383          *
    384          * @param animation The animation which was canceled.
    385          */
    386         void onAnimationCancel(Animator animation);
    387 
    388         /**
    389          * <p>Notifies the repetition of the animation.</p>
    390          *
    391          * @param animation The animation which was repeated.
    392          */
    393         void onAnimationRepeat(Animator animation);
    394     }
    395 
    396     /**
    397      * A pause listener receives notifications from an animation when the
    398      * animation is {@link #pause() paused} or {@link #resume() resumed}.
    399      *
    400      * @see #addPauseListener(AnimatorPauseListener)
    401      */
    402     public static interface AnimatorPauseListener {
    403         /**
    404          * <p>Notifies that the animation was paused.</p>
    405          *
    406          * @param animation The animaton being paused.
    407          * @see #pause()
    408          */
    409         void onAnimationPause(Animator animation);
    410 
    411         /**
    412          * <p>Notifies that the animation was resumed, after being
    413          * previously paused.</p>
    414          *
    415          * @param animation The animation being resumed.
    416          * @see #resume()
    417          */
    418         void onAnimationResume(Animator animation);
    419     }
    420 }
    421