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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.TestApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.content.pm.ActivityInfo.Config;
24 import android.content.res.ConstantState;
25 import android.os.Build;
26 import android.util.LongArray;
27 
28 import java.util.ArrayList;
29 
30 /**
31  * This is the superclass for classes which provide basic support for animations which can be
32  * started, ended, and have <code>AnimatorListeners</code> added to them.
33  */
34 public abstract class Animator implements Cloneable {
35 
36     /**
37      * The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
38      */
39     public static final long DURATION_INFINITE = -1;
40     /**
41      * The set of listeners to be sent events through the life of an animation.
42      */
43     ArrayList<AnimatorListener> mListeners = null;
44 
45     /**
46      * The set of listeners to be sent pause/resume events through the life
47      * of an animation.
48      */
49     ArrayList<AnimatorPauseListener> mPauseListeners = null;
50 
51     /**
52      * Whether this animator is currently in a paused state.
53      */
54     boolean mPaused = false;
55 
56     /**
57      * A set of flags which identify the type of configuration changes that can affect this
58      * Animator. Used by the Animator cache.
59      */
60     @Config int mChangingConfigurations = 0;
61 
62     /**
63      * If this animator is inflated from a constant state, keep a reference to it so that
64      * ConstantState will not be garbage collected until this animator is collected
65      */
66     private AnimatorConstantState mConstantState;
67 
68     /**
69      * backing field for backgroundPauseDelay property. This could be simply a hardcoded
70      * value in AnimationHandler, but it is useful to be able to change the value in tests.
71      */
72     private static long sBackgroundPauseDelay = 1000;
73 
74     /**
75      * A cache of the values in a list. Used so that when calling the list, we have a copy
76      * of it in case the list is modified while iterating. The array can be reused to avoid
77      * allocation on every notification.
78      */
79     private Object[] mCachedList;
80 
81     /**
82      * Tracks whether we've notified listeners of the onAnimationStart() event. This can be
83      * complex to keep track of since we notify listeners at different times depending on
84      * startDelay and whether start() was called before end().
85      */
86     boolean mStartListenersCalled = false;
87 
88     /**
89      * Sets the duration for delaying pausing animators when apps go into the background.
90      * Used by AnimationHandler when requested to pause animators.
91      *
92      * @hide
93      */
94     @TestApi
setBackgroundPauseDelay(long value)95     public static void setBackgroundPauseDelay(long value) {
96         sBackgroundPauseDelay = value;
97     }
98 
99     /**
100      * Gets the duration for delaying pausing animators when apps go into the background.
101      * Used by AnimationHandler when requested to pause animators.
102      *
103      * @hide
104      */
105     @TestApi
getBackgroundPauseDelay()106     public static long getBackgroundPauseDelay() {
107         return sBackgroundPauseDelay;
108     }
109 
110     /**
111      * Sets the behavior of animator pausing when apps go into the background.
112      * This is exposed as a test API for verification, but is intended for use by internal/
113      * platform code, potentially for use by a system property that could disable it
114      * system wide.
115      *
116      * @param enable Enable (default behavior) or disable background pausing behavior.
117      * @hide
118      */
119     @TestApi
setAnimatorPausingEnabled(boolean enable)120     public static void setAnimatorPausingEnabled(boolean enable) {
121         AnimationHandler.setAnimatorPausingEnabled(enable);
122         AnimationHandler.setOverrideAnimatorPausingSystemProperty(!enable);
123     }
124 
125     /**
126      * Starts this animation. If the animation has a nonzero startDelay, the animation will start
127      * running after that delay elapses. A non-delayed animation will have its initial
128      * value(s) set immediately, followed by calls to
129      * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator.
130      *
131      * <p>The animation started by calling this method will be run on the thread that called
132      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
133      * this is not the case). Also, if the animation will animate
134      * properties of objects in the view hierarchy, then the calling thread should be the UI
135      * thread for that view hierarchy.</p>
136      *
137      */
start()138     public void start() {
139     }
140 
141     /**
142      * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
143      * stop in its tracks, sending an
144      * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
145      * its listeners, followed by an
146      * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
147      *
148      * <p>This method must be called on the thread that is running the animation.</p>
149      */
cancel()150     public void cancel() {
151     }
152 
153     /**
154      * Ends the animation. This causes the animation to assign the end value of the property being
155      * animated, then calling the
156      * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
157      * its listeners.
158      *
159      * <p>This method must be called on the thread that is running the animation.</p>
160      */
end()161     public void end() {
162     }
163 
164     /**
165      * Pauses a running animation. This method should only be called on the same thread on
166      * which the animation was started. If the animation has not yet been {@link
167      * #isStarted() started} or has since ended, then the call is ignored. Paused
168      * animations can be resumed by calling {@link #resume()}.
169      *
170      * @see #resume()
171      * @see #isPaused()
172      * @see AnimatorPauseListener
173      */
pause()174     public void pause() {
175         // We only want to pause started Animators or animators that setCurrentPlayTime()
176         // have been called on. mStartListenerCalled will be true if seek has happened.
177         if ((isStarted() || mStartListenersCalled) && !mPaused) {
178             mPaused = true;
179             notifyPauseListeners(AnimatorCaller.ON_PAUSE);
180         }
181     }
182 
183     /**
184      * Resumes a paused animation, causing the animator to pick up where it left off
185      * when it was paused. This method should only be called on the same thread on
186      * which the animation was started. Calls to resume() on an animator that is
187      * not currently paused will be ignored.
188      *
189      * @see #pause()
190      * @see #isPaused()
191      * @see AnimatorPauseListener
192      */
resume()193     public void resume() {
194         if (mPaused) {
195             mPaused = false;
196             notifyPauseListeners(AnimatorCaller.ON_RESUME);
197         }
198     }
199 
200     /**
201      * Returns whether this animator is currently in a paused state.
202      *
203      * @return True if the animator is currently paused, false otherwise.
204      *
205      * @see #pause()
206      * @see #resume()
207      */
isPaused()208     public boolean isPaused() {
209         return mPaused;
210     }
211 
212     /**
213      * The amount of time, in milliseconds, to delay processing the animation
214      * after {@link #start()} is called.
215      *
216      * @return the number of milliseconds to delay running the animation
217      */
getStartDelay()218     public abstract long getStartDelay();
219 
220     /**
221      * The amount of time, in milliseconds, to delay processing the animation
222      * after {@link #start()} is called.
223 
224      * @param startDelay The amount of the delay, in milliseconds
225      */
setStartDelay(long startDelay)226     public abstract void setStartDelay(long startDelay);
227 
228     /**
229      * Sets the duration of the animation.
230      *
231      * @param duration The length of the animation, in milliseconds.
232      */
setDuration(long duration)233     public abstract Animator setDuration(long duration);
234 
235     /**
236      * Gets the duration of the animation.
237      *
238      * @return The length of the animation, in milliseconds.
239      */
getDuration()240     public abstract long getDuration();
241 
242     /**
243      * Gets the total duration of the animation, accounting for animation sequences, start delay,
244      * and repeating. Return {@link #DURATION_INFINITE} if the duration is infinite.
245      *
246      * @return  Total time an animation takes to finish, starting from the time {@link #start()}
247      *          is called. {@link #DURATION_INFINITE} will be returned if the animation or any
248      *          child animation repeats infinite times.
249      */
getTotalDuration()250     public long getTotalDuration() {
251         long duration = getDuration();
252         if (duration == DURATION_INFINITE) {
253             return DURATION_INFINITE;
254         } else {
255             return getStartDelay() + duration;
256         }
257     }
258 
259     /**
260      * The time interpolator used in calculating the elapsed fraction of the
261      * animation. The interpolator determines whether the animation runs with
262      * linear or non-linear motion, such as acceleration and deceleration. The
263      * default value is {@link android.view.animation.AccelerateDecelerateInterpolator}.
264      *
265      * @param value the interpolator to be used by this animation
266      */
setInterpolator(TimeInterpolator value)267     public abstract void setInterpolator(TimeInterpolator value);
268 
269     /**
270      * Returns the timing interpolator that this animation uses.
271      *
272      * @return The timing interpolator for this animation.
273      */
getInterpolator()274     public TimeInterpolator getInterpolator() {
275         return null;
276     }
277 
278     /**
279      * Returns whether this Animator is currently running (having been started and gone past any
280      * initial startDelay period and not yet ended).
281      *
282      * @return Whether the Animator is running.
283      */
isRunning()284     public abstract boolean isRunning();
285 
286     /**
287      * Returns whether this Animator has been started and not yet ended. For reusable
288      * Animators (which most Animators are, apart from the one-shot animator produced by
289      * {@link android.view.ViewAnimationUtils#createCircularReveal(
290      * android.view.View, int, int, float, float) createCircularReveal()}),
291      * this state is a superset of {@link #isRunning()}, because an Animator with a
292      * nonzero {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during
293      * the delay phase, whereas {@link #isRunning()} will return true only after the delay phase
294      * is complete. Non-reusable animators will always return true after they have been
295      * started, because they cannot return to a non-started state.
296      *
297      * @return Whether the Animator has been started and not yet ended.
298      */
isStarted()299     public boolean isStarted() {
300         // Default method returns value for isRunning(). Subclasses should override to return a
301         // real value.
302         return isRunning();
303     }
304 
305     /**
306      * Adds a listener to the set of listeners that are sent events through the life of an
307      * animation, such as start, repeat, and end.
308      *
309      * @param listener the listener to be added to the current set of listeners for this animation.
310      */
addListener(AnimatorListener listener)311     public void addListener(AnimatorListener listener) {
312         if (mListeners == null) {
313             mListeners = new ArrayList<AnimatorListener>();
314         }
315         mListeners.add(listener);
316     }
317 
318     /**
319      * Removes a listener from the set listening to this animation.
320      *
321      * @param listener the listener to be removed from the current set of listeners for this
322      *                 animation.
323      */
removeListener(AnimatorListener listener)324     public void removeListener(AnimatorListener listener) {
325         if (mListeners == null) {
326             return;
327         }
328         mListeners.remove(listener);
329         if (mListeners.size() == 0) {
330             mListeners = null;
331         }
332     }
333 
334     /**
335      * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
336      * listening for events on this <code>Animator</code> object.
337      *
338      * @return ArrayList<AnimatorListener> The set of listeners.
339      */
getListeners()340     public ArrayList<AnimatorListener> getListeners() {
341         return mListeners;
342     }
343 
344     /**
345      * Adds a pause listener to this animator.
346      *
347      * @param listener the listener to be added to the current set of pause listeners
348      * for this animation.
349      */
addPauseListener(AnimatorPauseListener listener)350     public void addPauseListener(AnimatorPauseListener listener) {
351         if (mPauseListeners == null) {
352             mPauseListeners = new ArrayList<AnimatorPauseListener>();
353         }
354         mPauseListeners.add(listener);
355     }
356 
357     /**
358      * Removes a pause listener from the set listening to this animation.
359      *
360      * @param listener the listener to be removed from the current set of pause
361      * listeners for this animation.
362      */
removePauseListener(AnimatorPauseListener listener)363     public void removePauseListener(AnimatorPauseListener listener) {
364         if (mPauseListeners == null) {
365             return;
366         }
367         mPauseListeners.remove(listener);
368         if (mPauseListeners.size() == 0) {
369             mPauseListeners = null;
370         }
371     }
372 
373     /**
374      * Removes all {@link #addListener(android.animation.Animator.AnimatorListener) listeners}
375      * and {@link #addPauseListener(android.animation.Animator.AnimatorPauseListener)
376      * pauseListeners} from this object.
377      */
removeAllListeners()378     public void removeAllListeners() {
379         if (mListeners != null) {
380             mListeners.clear();
381             mListeners = null;
382         }
383         if (mPauseListeners != null) {
384             mPauseListeners.clear();
385             mPauseListeners = null;
386         }
387     }
388 
389     /**
390      * Return a mask of the configuration parameters for which this animator may change, requiring
391      * that it should be re-created from Resources. The default implementation returns whatever
392      * value was provided through setChangingConfigurations(int) or 0 by default.
393      *
394      * @return Returns a mask of the changing configuration parameters, as defined by
395      * {@link android.content.pm.ActivityInfo}.
396      * @see android.content.pm.ActivityInfo
397      * @hide
398      */
getChangingConfigurations()399     public @Config int getChangingConfigurations() {
400         return mChangingConfigurations;
401     }
402 
403     /**
404      * Set a mask of the configuration parameters for which this animator may change, requiring
405      * that it be re-created from resource.
406      *
407      * @param configs A mask of the changing configuration parameters, as
408      * defined by {@link android.content.pm.ActivityInfo}.
409      *
410      * @see android.content.pm.ActivityInfo
411      * @hide
412      */
setChangingConfigurations(@onfig int configs)413     public void setChangingConfigurations(@Config int configs) {
414         mChangingConfigurations = configs;
415     }
416 
417     /**
418      * Sets the changing configurations value to the union of the current changing configurations
419      * and the provided configs.
420      * This method is called while loading the animator.
421      * @hide
422      */
appendChangingConfigurations(@onfig int configs)423     public void appendChangingConfigurations(@Config int configs) {
424         mChangingConfigurations |= configs;
425     }
426 
427     /**
428      * Return a {@link android.content.res.ConstantState} instance that holds the shared state of
429      * this Animator.
430      * <p>
431      * This constant state is used to create new instances of this animator when needed, instead
432      * of re-loading it from resources. Default implementation creates a new
433      * {@link AnimatorConstantState}. You can override this method to provide your custom logic or
434      * return null if you don't want this animator to be cached.
435      *
436      * @return The ConfigurationBoundResourceCache.BaseConstantState associated to this Animator.
437      * @see android.content.res.ConstantState
438      * @see #clone()
439      * @hide
440      */
createConstantState()441     public ConstantState<Animator> createConstantState() {
442         return new AnimatorConstantState(this);
443     }
444 
445     @Override
clone()446     public Animator clone() {
447         try {
448             final Animator anim = (Animator) super.clone();
449             if (mListeners != null) {
450                 anim.mListeners = new ArrayList<AnimatorListener>(mListeners);
451             }
452             if (mPauseListeners != null) {
453                 anim.mPauseListeners = new ArrayList<AnimatorPauseListener>(mPauseListeners);
454             }
455             anim.mCachedList = null;
456             anim.mStartListenersCalled = false;
457             return anim;
458         } catch (CloneNotSupportedException e) {
459            throw new AssertionError();
460         }
461     }
462 
463     /**
464      * This method tells the object to use appropriate information to extract
465      * starting values for the animation. For example, a AnimatorSet object will pass
466      * this call to its child objects to tell them to set up the values. A
467      * ObjectAnimator object will use the information it has about its target object
468      * and PropertyValuesHolder objects to get the start values for its properties.
469      * A ValueAnimator object will ignore the request since it does not have enough
470      * information (such as a target object) to gather these values.
471      */
setupStartValues()472     public void setupStartValues() {
473     }
474 
475     /**
476      * This method tells the object to use appropriate information to extract
477      * ending values for the animation. For example, a AnimatorSet object will pass
478      * this call to its child objects to tell them to set up the values. A
479      * ObjectAnimator object will use the information it has about its target object
480      * and PropertyValuesHolder objects to get the start values for its properties.
481      * A ValueAnimator object will ignore the request since it does not have enough
482      * information (such as a target object) to gather these values.
483      */
setupEndValues()484     public void setupEndValues() {
485     }
486 
487     /**
488      * Sets the target object whose property will be animated by this animation. Not all subclasses
489      * operate on target objects (for example, {@link ValueAnimator}, but this method
490      * is on the superclass for the convenience of dealing generically with those subclasses
491      * that do handle targets.
492      * <p>
493      * <strong>Note:</strong> The target is stored as a weak reference internally to avoid leaking
494      * resources by having animators directly reference old targets. Therefore, you should
495      * ensure that animator targets always have a hard reference elsewhere.
496      *
497      * @param target The object being animated
498      */
setTarget(@ullable Object target)499     public void setTarget(@Nullable Object target) {
500     }
501 
502     // Hide reverse() and canReverse() for now since reverse() only work for simple
503     // cases, like we don't support sequential, neither startDelay.
504     // TODO: make reverse() works for all the Animators.
505     /**
506      * @hide
507      */
canReverse()508     public boolean canReverse() {
509         return false;
510     }
511 
512     /**
513      * @hide
514      */
515     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
reverse()516     public void reverse() {
517         throw new IllegalStateException("Reverse is not supported");
518     }
519 
520     // Pulse an animation frame into the animation.
pulseAnimationFrame(long frameTime)521     boolean pulseAnimationFrame(long frameTime) {
522         // TODO: Need to find a better signal than this. There's a bug in SystemUI that's preventing
523         // returning !isStarted() from working.
524         return false;
525     }
526 
527     /**
528      * Internal use only.
529      * This call starts the animation in regular or reverse direction without requiring them to
530      * register frame callbacks. The caller will be responsible for all the subsequent animation
531      * pulses. Specifically, the caller needs to call doAnimationFrame(...) for the animation on
532      * every frame.
533      *
534      * @param inReverse whether the animation should play in reverse direction
535      */
startWithoutPulsing(boolean inReverse)536     void startWithoutPulsing(boolean inReverse) {
537         if (inReverse) {
538             reverse();
539         } else {
540             start();
541         }
542     }
543 
544     /**
545      * Internal use only.
546      * Skips the animation value to end/start, depending on whether the play direction is forward
547      * or backward.
548      *
549      * @param inReverse whether the end value is based on a reverse direction. If yes, this is
550      *                  equivalent to skip to start value in a forward playing direction.
551      */
skipToEndValue(boolean inReverse)552     void skipToEndValue(boolean inReverse) {}
553 
554     /**
555      * Internal use only.
556      *
557      * Returns whether the animation has start/end values setup. For most of the animations, this
558      * should always be true. For ObjectAnimators, the start values are setup in the initialization
559      * of the animation.
560      */
isInitialized()561     boolean isInitialized() {
562         return true;
563     }
564 
565     /**
566      * Internal use only. Changes the value of the animator as if currentPlayTime has passed since
567      * the start of the animation. Therefore, currentPlayTime includes the start delay, and any
568      * repetition. lastPlayTime is similar and is used to calculate how many repeats have been
569      * done between the two times.
570      */
animateValuesInRange(long currentPlayTime, long lastPlayTime)571     void animateValuesInRange(long currentPlayTime, long lastPlayTime) {}
572 
573     /**
574      * Internal use only. This animates any animation that has ended since lastPlayTime.
575      * If an animation hasn't been finished, no change will be made.
576      */
animateSkipToEnds(long currentPlayTime, long lastPlayTime)577     void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {}
578 
579     /**
580      * Internal use only. Adds all start times (after delay) to and end times to times.
581      * The value must include offset.
582      */
getStartAndEndTimes(LongArray times, long offset)583     void getStartAndEndTimes(LongArray times, long offset) {
584         long startTime = offset + getStartDelay();
585         if (times.indexOf(startTime) < 0) {
586             times.add(startTime);
587         }
588         long duration = getTotalDuration();
589         if (duration != DURATION_INFINITE) {
590             long endTime = duration + offset;
591             if (times.indexOf(endTime) < 0) {
592                 times.add(endTime);
593             }
594         }
595     }
596 
597     /**
598      * Calls notification for each AnimatorListener.
599      *
600      * @param notification The notification method to call on each listener.
601      * @param isReverse When this is used with start/end, this is the isReverse parameter. For
602      *                  other calls, this is ignored.
603      */
notifyListeners( AnimatorCaller<AnimatorListener, Animator> notification, boolean isReverse )604     void notifyListeners(
605             AnimatorCaller<AnimatorListener, Animator> notification,
606             boolean isReverse
607     ) {
608         callOnList(mListeners, notification, this, isReverse);
609     }
610 
611     /**
612      * Call pause/resume on each AnimatorPauseListener.
613      *
614      * @param notification Either ON_PAUSE or ON_RESUME to call onPause or onResume on each
615      *                     listener.
616      */
notifyPauseListeners(AnimatorCaller<AnimatorPauseListener, Animator> notification)617     void notifyPauseListeners(AnimatorCaller<AnimatorPauseListener, Animator> notification) {
618         callOnList(mPauseListeners, notification, this, false);
619     }
620 
notifyStartListeners(boolean isReversing)621     void notifyStartListeners(boolean isReversing) {
622         boolean startListenersCalled = mStartListenersCalled;
623         mStartListenersCalled = true;
624         if (mListeners != null && !startListenersCalled) {
625             notifyListeners(AnimatorCaller.ON_START, isReversing);
626         }
627     }
628 
notifyEndListeners(boolean isReversing)629     void notifyEndListeners(boolean isReversing) {
630         boolean startListenersCalled = mStartListenersCalled;
631         mStartListenersCalled = false;
632         if (mListeners != null && startListenersCalled) {
633             notifyListeners(AnimatorCaller.ON_END, isReversing);
634         }
635     }
636 
637     /**
638      * Calls <code>call</code> for every item in <code>list</code> with <code>animator</code> and
639      * <code>isReverse</code> as parameters.
640      *
641      * @param list The list of items to make calls on.
642      * @param call The method to call for each item in list.
643      * @param animator The animator parameter of call.
644      * @param isReverse The isReverse parameter of call.
645      * @param <T> The item type of list
646      * @param <A> The Animator type of animator.
647      */
callOnList( ArrayList<T> list, AnimatorCaller<T, A> call, A animator, boolean isReverse )648     <T, A> void callOnList(
649             ArrayList<T> list,
650             AnimatorCaller<T, A> call,
651             A animator,
652             boolean isReverse
653     ) {
654         int size = list == null ? 0 : list.size();
655         if (size > 0) {
656             // Try to reuse mCacheList to store the items of list.
657             Object[] array;
658             if (mCachedList == null || mCachedList.length < size) {
659                 array = new Object[size];
660             } else {
661                 array = mCachedList;
662                 // Clear it in case there is some reentrancy
663                 mCachedList = null;
664             }
665             list.toArray(array);
666             for (int i = 0; i < size; i++) {
667                 //noinspection unchecked
668                 T item = (T) array[i];
669                 call.call(item, animator, isReverse);
670                 array[i] = null;
671             }
672             // Store it for the next call so we can reuse this array, if needed.
673             mCachedList = array;
674         }
675     }
676 
677     /**
678      * <p>An animation listener receives notifications from an animation.
679      * Notifications indicate animation related events, such as the end or the
680      * repetition of the animation.</p>
681      */
682     public static interface AnimatorListener {
683 
684         /**
685          * <p>Notifies the start of the animation as well as the animation's overall play direction.
686          * This method's default behavior is to call {@link #onAnimationStart(Animator)}. This
687          * method can be overridden, though not required, to get the additional play direction info
688          * when an animation starts. Skipping calling super when overriding this method results in
689          * {@link #onAnimationStart(Animator)} not getting called.
690          *
691          * @param animation The started animation.
692          * @param isReverse Whether the animation is playing in reverse.
693          */
onAnimationStart(@onNull Animator animation, boolean isReverse)694         default void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
695             onAnimationStart(animation);
696         }
697 
698         /**
699          * <p>Notifies the end of the animation. This callback is not invoked
700          * for animations with repeat count set to INFINITE.</p>
701          *
702          * <p>This method's default behavior is to call {@link #onAnimationEnd(Animator)}. This
703          * method can be overridden, though not required, to get the additional play direction info
704          * when an animation ends. Skipping calling super when overriding this method results in
705          * {@link #onAnimationEnd(Animator)} not getting called.
706          *
707          * @param animation The animation which reached its end.
708          * @param isReverse Whether the animation is playing in reverse.
709          */
onAnimationEnd(@onNull Animator animation, boolean isReverse)710         default void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
711             onAnimationEnd(animation);
712         }
713 
714         /**
715          * <p>Notifies the start of the animation.</p>
716          *
717          * @param animation The started animation.
718          */
onAnimationStart(@onNull Animator animation)719         void onAnimationStart(@NonNull Animator animation);
720 
721         /**
722          * <p>Notifies the end of the animation. This callback is not invoked
723          * for animations with repeat count set to INFINITE.</p>
724          *
725          * @param animation The animation which reached its end.
726          */
onAnimationEnd(@onNull Animator animation)727         void onAnimationEnd(@NonNull Animator animation);
728 
729         /**
730          * <p>Notifies the cancellation of the animation. This callback is not invoked
731          * for animations with repeat count set to INFINITE.</p>
732          *
733          * @param animation The animation which was canceled.
734          */
onAnimationCancel(@onNull Animator animation)735         void onAnimationCancel(@NonNull Animator animation);
736 
737         /**
738          * <p>Notifies the repetition of the animation.</p>
739          *
740          * @param animation The animation which was repeated.
741          */
onAnimationRepeat(@onNull Animator animation)742         void onAnimationRepeat(@NonNull Animator animation);
743     }
744 
745     /**
746      * A pause listener receives notifications from an animation when the
747      * animation is {@link #pause() paused} or {@link #resume() resumed}.
748      *
749      * @see #addPauseListener(AnimatorPauseListener)
750      */
751     public static interface AnimatorPauseListener {
752         /**
753          * <p>Notifies that the animation was paused.</p>
754          *
755          * @param animation The animaton being paused.
756          * @see #pause()
757          */
onAnimationPause(@onNull Animator animation)758         void onAnimationPause(@NonNull Animator animation);
759 
760         /**
761          * <p>Notifies that the animation was resumed, after being
762          * previously paused.</p>
763          *
764          * @param animation The animation being resumed.
765          * @see #resume()
766          */
onAnimationResume(@onNull Animator animation)767         void onAnimationResume(@NonNull Animator animation);
768     }
769 
770     /**
771      * <p>Whether or not the Animator is allowed to run asynchronously off of
772      * the UI thread. This is a hint that informs the Animator that it is
773      * OK to run the animation off-thread, however the Animator may decide
774      * that it must run the animation on the UI thread anyway.
775      *
776      * <p>Regardless of whether or not the animation runs asynchronously, all
777      * listener callbacks will be called on the UI thread.</p>
778      *
779      * <p>To be able to use this hint the following must be true:</p>
780      * <ol>
781      * <li>The animator is immutable while {@link #isStarted()} is true. Requests
782      *    to change duration, delay, etc... may be ignored.</li>
783      * <li>Lifecycle callback events may be asynchronous. Events such as
784      *    {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or
785      *    {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed
786      *    as they must be posted back to the UI thread, and any actions performed
787      *    by those callbacks (such as starting new animations) will not happen
788      *    in the same frame.</li>
789      * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...)
790      *    may be asynchronous. It is guaranteed that all state changes that are
791      *    performed on the UI thread in the same frame will be applied as a single
792      *    atomic update, however that frame may be the current frame,
793      *    the next frame, or some future frame. This will also impact the observed
794      *    state of the Animator. For example, {@link #isStarted()} may still return true
795      *    after a call to {@link #end()}. Using the lifecycle callbacks is preferred over
796      *    queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()}
797      *    for this reason.</li>
798      * </ol>
799      * @hide
800      */
setAllowRunningAsynchronously(boolean mayRunAsync)801     public void setAllowRunningAsynchronously(boolean mayRunAsync) {
802         // It is up to subclasses to support this, if they can.
803     }
804 
805     /**
806      * Creates a {@link ConstantState} which holds changing configurations information associated
807      * with the given Animator.
808      * <p>
809      * When {@link #newInstance()} is called, default implementation clones the Animator.
810      */
811     private static class AnimatorConstantState extends ConstantState<Animator> {
812 
813         final Animator mAnimator;
814         @Config int mChangingConf;
815 
AnimatorConstantState(Animator animator)816         public AnimatorConstantState(Animator animator) {
817             mAnimator = animator;
818             // ensure a reference back to here so that constante state is not gc'ed.
819             mAnimator.mConstantState = this;
820             mChangingConf = mAnimator.getChangingConfigurations();
821         }
822 
823         @Override
getChangingConfigurations()824         public @Config int getChangingConfigurations() {
825             return mChangingConf;
826         }
827 
828         @Override
newInstance()829         public Animator newInstance() {
830             final Animator clone = mAnimator.clone();
831             clone.mConstantState = this;
832             return clone;
833         }
834     }
835 
836     /**
837      * Internally used by {@link #callOnList(ArrayList, AnimatorCaller, Object, boolean)} to
838      * make a call on all children of a list. This can be for start, stop, pause, cancel, update,
839      * etc notifications.
840      *
841      * @param <T> The type of listener to make the call on
842      * @param <A> The type of animator that is passed as a parameter
843      */
844     interface AnimatorCaller<T, A> {
call(T listener, A animator, boolean isReverse)845         void call(T listener, A animator, boolean isReverse);
846 
847         AnimatorCaller<AnimatorListener, Animator> ON_START = AnimatorListener::onAnimationStart;
848         AnimatorCaller<AnimatorListener, Animator> ON_END = AnimatorListener::onAnimationEnd;
849         AnimatorCaller<AnimatorListener, Animator> ON_CANCEL =
850                 (listener, animator, isReverse) -> listener.onAnimationCancel(animator);
851         AnimatorCaller<AnimatorListener, Animator> ON_REPEAT =
852                 (listener, animator, isReverse) -> listener.onAnimationRepeat(animator);
853         AnimatorCaller<AnimatorPauseListener, Animator> ON_PAUSE =
854                 (listener, animator, isReverse) -> listener.onAnimationPause(animator);
855         AnimatorCaller<AnimatorPauseListener, Animator> ON_RESUME =
856                 (listener, animator, isReverse) -> listener.onAnimationResume(animator);
857         AnimatorCaller<ValueAnimator.AnimatorUpdateListener, ValueAnimator> ON_UPDATE =
858                 (listener, animator, isReverse) -> listener.onAnimationUpdate(animator);
859     }
860 }
861