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