1/*
2 * Copyright (C) 2016 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
17package android.support.transition;
18
19import android.animation.Animator;
20import android.animation.TimeInterpolator;
21import android.os.Build;
22import android.support.annotation.IdRes;
23import android.support.annotation.NonNull;
24import android.support.annotation.Nullable;
25import android.view.SurfaceView;
26import android.view.TextureView;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.Spinner;
30
31import java.util.List;
32
33/**
34 * A Transition holds information about animations that will be run on its
35 * targets during a scene change. Subclasses of this abstract class may
36 * choreograph several child transitions ({@link TransitionSet} or they may
37 * perform custom animations themselves. Any Transition has two main jobs:
38 * (1) capture property values, and (2) play animations based on changes to
39 * captured property values. A custom transition knows what property values
40 * on View objects are of interest to it, and also knows how to animate
41 * changes to those values. For example, the {@link Fade} transition tracks
42 * changes to visibility-related properties and is able to construct and run
43 * animations that fade items in or out based on changes to those properties.
44 *
45 * <p>Note: Transitions may not work correctly with either {@link SurfaceView}
46 * or {@link TextureView}, due to the way that these views are displayed
47 * on the screen. For SurfaceView, the problem is that the view is updated from
48 * a non-UI thread, so changes to the view due to transitions (such as moving
49 * and resizing the view) may be out of sync with the display inside those bounds.
50 * TextureView is more compatible with transitions in general, but some
51 * specific transitions (such as {@link Fade}) may not be compatible
52 * with TextureView because they rely on {@link android.view.ViewOverlay}
53 * functionality, which does not currently work with TextureView.</p>
54 *
55 * <p>Unlike the platform version, this does not support declaration by XML resources.</p>
56 */
57public abstract class Transition implements TransitionInterface {
58
59    /* package */ TransitionImpl mImpl;
60
61    /**
62     * Constructs a Transition object with no target objects. A transition with
63     * no targets defaults to running on all target objects in the scene hierarchy
64     * (if the transition is not contained in a TransitionSet), or all target
65     * objects passed down from its parent (if it is in a TransitionSet).
66     */
67    public Transition() {
68        this(false);
69    }
70
71    // Hidden constructor for built-in transitions
72    Transition(boolean deferred) {
73        if (!deferred) {
74            if (Build.VERSION.SDK_INT >= 23) {
75                mImpl = new TransitionApi23();
76            } else if (Build.VERSION.SDK_INT >= 19) {
77                mImpl = new TransitionKitKat();
78            } else {
79                mImpl = new TransitionIcs();
80            }
81            mImpl.init(this);
82        }
83    }
84
85    /**
86     * Adds a listener to the set of listeners that are sent events through the
87     * life of an animation, such as start, repeat, and end.
88     *
89     * @param listener the listener to be added to the current set of listeners
90     *                 for this animation.
91     * @return This transition object.
92     */
93    @NonNull
94    public Transition addListener(@NonNull TransitionListener listener) {
95        mImpl.addListener(listener);
96        return this;
97    }
98
99    /**
100     * Sets the target view instances that this Transition is interested in
101     * animating. By default, there are no targets, and a Transition will
102     * listen for changes on every view in the hierarchy below the sceneRoot
103     * of the Scene being transitioned into. Setting targets constrains
104     * the Transition to only listen for, and act on, these views.
105     * All other views will be ignored.
106     *
107     * <p>The target list is like the {@link #addTarget(int) targetId}
108     * list except this list specifies the actual View instances, not the ids
109     * of the views. This is an important distinction when scene changes involve
110     * view hierarchies which have been inflated separately; different views may
111     * share the same id but not actually be the same instance. If the transition
112     * should treat those views as the same, then {@link #addTarget(int)} should be used
113     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
114     * changes all within the same view hierarchy, among views which do not
115     * necessarily have ids set on them, then the target list of views may be more
116     * convenient.</p>
117     *
118     * @param target A View on which the Transition will act, must be non-null.
119     * @return The Transition to which the target is added.
120     * Returning the same object makes it easier to chain calls during
121     * construction, such as
122     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
123     * @see #addTarget(int)
124     */
125    @NonNull
126    public Transition addTarget(@NonNull View target) {
127        mImpl.addTarget(target);
128        return this;
129    }
130
131    /**
132     * Adds the id of a target view that this Transition is interested in
133     * animating. By default, there are no targetIds, and a Transition will
134     * listen for changes on every view in the hierarchy below the sceneRoot
135     * of the Scene being transitioned into. Setting targetIds constrains
136     * the Transition to only listen for, and act on, views with these IDs.
137     * Views with different IDs, or no IDs whatsoever, will be ignored.
138     *
139     * <p>Note that using ids to specify targets implies that ids should be unique
140     * within the view hierarchy underneath the scene root.</p>
141     *
142     * @param targetId The id of a target view, must be a positive number.
143     * @return The Transition to which the targetId is added.
144     * Returning the same object makes it easier to chain calls during
145     * construction, such as
146     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
147     * @see View#getId()
148     */
149    @NonNull
150    public Transition addTarget(@IdRes int targetId) {
151        mImpl.addTarget(targetId);
152        return this;
153    }
154
155    /**
156     * Captures the values in the end scene for the properties that this
157     * transition monitors. These values are then passed as the endValues
158     * structure in a later call to
159     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
160     * The main concern for an implementation is what the
161     * properties are that the transition cares about and what the values are
162     * for all of those properties. The start and end values will be compared
163     * later during the
164     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
165     * method to determine what, if any, animations, should be run.
166     *
167     * <p>Subclasses must implement this method. The method should only be called by the
168     * transition system; it is not intended to be called from external classes.</p>
169     *
170     * @param transitionValues The holder for any values that the Transition
171     *                         wishes to store. Values are stored in the <code>values</code> field
172     *                         of this TransitionValues object and are keyed from
173     *                         a String value. For example, to store a view's rotation value,
174     *                         a transition might call
175     *                         <code>transitionValues.values.put("appname:transitionname:rotation",
176     *                         view.getRotation())</code>. The target view will already be stored
177     *                         in
178     *                         the transitionValues structure when this method is called.
179     * @see #captureStartValues(TransitionValues)
180     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
181     */
182    @Override
183    public abstract void captureEndValues(@NonNull TransitionValues transitionValues);
184
185    /**
186     * Captures the values in the start scene for the properties that this
187     * transition monitors. These values are then passed as the startValues
188     * structure in a later call to
189     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
190     * The main concern for an implementation is what the
191     * properties are that the transition cares about and what the values are
192     * for all of those properties. The start and end values will be compared
193     * later during the
194     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
195     * method to determine what, if any, animations, should be run.
196     *
197     * <p>Subclasses must implement this method. The method should only be called by the
198     * transition system; it is not intended to be called from external classes.</p>
199     *
200     * @param transitionValues The holder for any values that the Transition
201     *                         wishes to store. Values are stored in the <code>values</code> field
202     *                         of this TransitionValues object and are keyed from
203     *                         a String value. For example, to store a view's rotation value,
204     *                         a transition might call
205     *                         <code>transitionValues.values.put("appname:transitionname:rotation",
206     *                         view.getRotation())</code>. The target view will already be stored
207     *                         in
208     *                         the transitionValues structure when this method is called.
209     * @see #captureEndValues(TransitionValues)
210     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
211     */
212    @Override
213    public abstract void captureStartValues(@NonNull TransitionValues transitionValues);
214
215    /**
216     * This method creates an animation that will be run for this transition
217     * given the information in the startValues and endValues structures captured
218     * earlier for the start and end scenes. Subclasses of Transition should override
219     * this method. The method should only be called by the transition system; it is
220     * not intended to be called from external classes.
221     *
222     * <p>This method is called by the transition's parent (all the way up to the
223     * topmost Transition in the hierarchy) with the sceneRoot and start/end
224     * values that the transition may need to set up initial target values
225     * and construct an appropriate animation. For example, if an overall
226     * Transition is a {@link TransitionSet} consisting of several
227     * child transitions in sequence, then some of the child transitions may
228     * want to set initial values on target views prior to the overall
229     * Transition commencing, to put them in an appropriate state for the
230     * delay between that start and the child Transition start time. For
231     * example, a transition that fades an item in may wish to set the starting
232     * alpha value to 0, to avoid it blinking in prior to the transition
233     * actually starting the animation. This is necessary because the scene
234     * change that triggers the Transition will automatically set the end-scene
235     * on all target views, so a Transition that wants to animate from a
236     * different value should set that value prior to returning from this method.</p>
237     *
238     * <p>Additionally, a Transition can perform logic to determine whether
239     * the transition needs to run on the given target and start/end values.
240     * For example, a transition that resizes objects on the screen may wish
241     * to avoid running for views which are not present in either the start
242     * or end scenes.</p>
243     *
244     * <p>If there is an animator created and returned from this method, the
245     * transition mechanism will apply any applicable duration, startDelay,
246     * and interpolator to that animation and start it. A return value of
247     * <code>null</code> indicates that no animation should run. The default
248     * implementation returns null.</p>
249     *
250     * <p>The method is called for every applicable target object, which is
251     * stored in the {@link TransitionValues#view} field.</p>
252     *
253     * @param sceneRoot   The root of the transition hierarchy.
254     * @param startValues The values for a specific target in the start scene.
255     * @param endValues   The values for the target in the end scene.
256     * @return A Animator to be started at the appropriate time in the
257     * overall transition for this scene change. A null value means no animation
258     * should be run.
259     */
260    @Override
261    @Nullable
262    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
263            @Nullable TransitionValues startValues, @Nullable TransitionValues endValues) {
264        return null;
265    }
266
267    /**
268     * Whether to add the children of given target to the list of target children
269     * to exclude from this transition. The <code>exclude</code> parameter specifies
270     * whether the target should be added to or removed from the excluded list.
271     *
272     * <p>Excluding targets is a general mechanism for allowing transitions to run on
273     * a view hierarchy while skipping target views that should not be part of
274     * the transition. For example, you may want to avoid animating children
275     * of a specific ListView or Spinner. Views can be excluded either by their
276     * id, or by their instance reference, or by the Class of that view
277     * (eg, {@link Spinner}).</p>
278     *
279     * @param target  The target to ignore when running this transition.
280     * @param exclude Whether to add the target to or remove the target from the
281     *                current list of excluded targets.
282     * @return This transition object.
283     * @see #excludeTarget(View, boolean)
284     * @see #excludeChildren(int, boolean)
285     * @see #excludeChildren(Class, boolean)
286     */
287    @NonNull
288    public Transition excludeChildren(@NonNull View target, boolean exclude) {
289        mImpl.excludeChildren(target, exclude);
290        return this;
291    }
292
293    /**
294     * Whether to add the children of the given id to the list of targets to exclude
295     * from this transition. The <code>exclude</code> parameter specifies whether
296     * the children of the target should be added to or removed from the excluded list.
297     * Excluding children in this way provides a simple mechanism for excluding all
298     * children of specific targets, rather than individually excluding each
299     * child individually.
300     *
301     * <p>Excluding targets is a general mechanism for allowing transitions to run on
302     * a view hierarchy while skipping target views that should not be part of
303     * the transition. For example, you may want to avoid animating children
304     * of a specific ListView or Spinner. Views can be excluded either by their
305     * id, or by their instance reference, or by the Class of that view
306     * (eg, {@link Spinner}).</p>
307     *
308     * @param targetId The id of a target whose children should be ignored when running
309     *                 this transition.
310     * @param exclude  Whether to add the target to or remove the target from the
311     *                 current list of excluded-child targets.
312     * @return This transition object.
313     * @see #excludeTarget(int, boolean)
314     * @see #excludeChildren(View, boolean)
315     * @see #excludeChildren(Class, boolean)
316     */
317    @NonNull
318    public Transition excludeChildren(@IdRes int targetId, boolean exclude) {
319        mImpl.excludeChildren(targetId, exclude);
320        return this;
321    }
322
323    /**
324     * Whether to add the given type to the list of types whose children should
325     * be excluded from this transition. The <code>exclude</code> parameter
326     * specifies whether the target type should be added to or removed from
327     * the excluded list.
328     *
329     * <p>Excluding targets is a general mechanism for allowing transitions to run on
330     * a view hierarchy while skipping target views that should not be part of
331     * the transition. For example, you may want to avoid animating children
332     * of a specific ListView or Spinner. Views can be excluded either by their
333     * id, or by their instance reference, or by the Class of that view
334     * (eg, {@link Spinner}).</p>
335     *
336     * @param type    The type to ignore when running this transition.
337     * @param exclude Whether to add the target type to or remove it from the
338     *                current list of excluded target types.
339     * @return This transition object.
340     * @see #excludeTarget(Class, boolean)
341     * @see #excludeChildren(int, boolean)
342     * @see #excludeChildren(View, boolean)
343     */
344    @NonNull
345    public Transition excludeChildren(@NonNull Class type, boolean exclude) {
346        mImpl.excludeChildren(type, exclude);
347        return this;
348    }
349
350    /**
351     * Whether to add the given target to the list of targets to exclude from this
352     * transition. The <code>exclude</code> parameter specifies whether the target
353     * should be added to or removed from the excluded list.
354     *
355     * <p>Excluding targets is a general mechanism for allowing transitions to run on
356     * a view hierarchy while skipping target views that should not be part of
357     * the transition. For example, you may want to avoid animating children
358     * of a specific ListView or Spinner. Views can be excluded either by their
359     * id, or by their instance reference, or by the Class of that view
360     * (eg, {@link Spinner}).</p>
361     *
362     * @param target  The target to ignore when running this transition.
363     * @param exclude Whether to add the target to or remove the target from the
364     *                current list of excluded targets.
365     * @return This transition object.
366     * @see #excludeChildren(View, boolean)
367     * @see #excludeTarget(int, boolean)
368     * @see #excludeTarget(Class, boolean)
369     */
370    @NonNull
371    public Transition excludeTarget(@NonNull View target, boolean exclude) {
372        mImpl.excludeTarget(target, exclude);
373        return this;
374    }
375
376    /**
377     * Whether to add the given id to the list of target ids to exclude from this
378     * transition. The <code>exclude</code> parameter specifies whether the target
379     * should be added to or removed from the excluded list.
380     *
381     * <p>Excluding targets is a general mechanism for allowing transitions to run on
382     * a view hierarchy while skipping target views that should not be part of
383     * the transition. For example, you may want to avoid animating children
384     * of a specific ListView or Spinner. Views can be excluded either by their
385     * id, or by their instance reference, or by the Class of that view
386     * (eg, {@link Spinner}).</p>
387     *
388     * @param targetId The id of a target to ignore when running this transition.
389     * @param exclude  Whether to add the target to or remove the target from the
390     *                 current list of excluded targets.
391     * @return This transition object.
392     * @see #excludeChildren(int, boolean)
393     * @see #excludeTarget(View, boolean)
394     * @see #excludeTarget(Class, boolean)
395     */
396    @NonNull
397    public Transition excludeTarget(@IdRes int targetId, boolean exclude) {
398        mImpl.excludeTarget(targetId, exclude);
399        return this;
400    }
401
402    /**
403     * Whether to add the given type to the list of types to exclude from this
404     * transition. The <code>exclude</code> parameter specifies whether the target
405     * type should be added to or removed from the excluded list.
406     *
407     * <p>Excluding targets is a general mechanism for allowing transitions to run on
408     * a view hierarchy while skipping target views that should not be part of
409     * the transition. For example, you may want to avoid animating children
410     * of a specific ListView or Spinner. Views can be excluded either by their
411     * id, or by their instance reference, or by the Class of that view
412     * (eg, {@link Spinner}).</p>
413     *
414     * @param type    The type to ignore when running this transition.
415     * @param exclude Whether to add the target type to or remove it from the
416     *                current list of excluded target types.
417     * @return This transition object.
418     * @see #excludeChildren(Class, boolean)
419     * @see #excludeTarget(int, boolean)
420     * @see #excludeTarget(View, boolean)
421     */
422    @NonNull
423    public Transition excludeTarget(@NonNull Class type, boolean exclude) {
424        mImpl.excludeTarget(type, exclude);
425        return this;
426    }
427
428    /**
429     * Returns the duration set on this transition. If no duration has been set,
430     * the returned value will be negative, indicating that resulting animators will
431     * retain their own durations.
432     *
433     * @return The duration set on this transition, in milliseconds, if one has been
434     * set, otherwise returns a negative number.
435     */
436    public long getDuration() {
437        return mImpl.getDuration();
438    }
439
440    /**
441     * Sets the duration of this transition. By default, there is no duration
442     * (indicated by a negative number), which means that the Animator created by
443     * the transition will have its own specified duration. If the duration of a
444     * Transition is set, that duration will override the Animator duration.
445     *
446     * @param duration The length of the animation, in milliseconds.
447     * @return This transition object.
448     * @attr name android:duration
449     */
450    @NonNull
451    public Transition setDuration(long duration) {
452        mImpl.setDuration(duration);
453        return this;
454    }
455
456    /**
457     * Returns the interpolator set on this transition. If no interpolator has been set,
458     * the returned value will be null, indicating that resulting animators will
459     * retain their own interpolators.
460     *
461     * @return The interpolator set on this transition, if one has been set, otherwise
462     * returns null.
463     */
464    @Nullable
465    public TimeInterpolator getInterpolator() {
466        return mImpl.getInterpolator();
467    }
468
469    /**
470     * Sets the interpolator of this transition. By default, the interpolator
471     * is null, which means that the Animator created by the transition
472     * will have its own specified interpolator. If the interpolator of a
473     * Transition is set, that interpolator will override the Animator interpolator.
474     *
475     * @param interpolator The time interpolator used by the transition
476     * @return This transition object.
477     * @attr name android:interpolator
478     */
479    @NonNull
480    public Transition setInterpolator(@Nullable TimeInterpolator interpolator) {
481        mImpl.setInterpolator(interpolator);
482        return this;
483    }
484
485    /**
486     * Returns the name of this Transition. This name is used internally to distinguish
487     * between different transitions to determine when interrupting transitions overlap.
488     * For example, a ChangeBounds running on the same target view as another ChangeBounds
489     * should determine whether the old transition is animating to different end values
490     * and should be canceled in favor of the new transition.
491     *
492     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
493     * but subclasses are free to override and return something different.</p>
494     *
495     * @return The name of this transition.
496     */
497    @NonNull
498    public String getName() {
499        return mImpl.getName();
500    }
501
502    /**
503     * Returns the startDelay set on this transition. If no startDelay has been set,
504     * the returned value will be negative, indicating that resulting animators will
505     * retain their own startDelays.
506     *
507     * @return The startDelay set on this transition, in milliseconds, if one has
508     * been set, otherwise returns a negative number.
509     */
510    public long getStartDelay() {
511        return mImpl.getStartDelay();
512    }
513
514    /**
515     * Sets the startDelay of this transition. By default, there is no delay
516     * (indicated by a negative number), which means that the Animator created by
517     * the transition will have its own specified startDelay. If the delay of a
518     * Transition is set, that delay will override the Animator delay.
519     *
520     * @param startDelay The length of the delay, in milliseconds.
521     * @return This transition object.
522     * @attr name android:startDelay
523     */
524    @NonNull
525    public Transition setStartDelay(long startDelay) {
526        mImpl.setStartDelay(startDelay);
527        return this;
528    }
529
530    /**
531     * Returns the array of target IDs that this transition limits itself to
532     * tracking and animating. If the array is null for both this method and
533     * {@link #getTargets()}, then this transition is
534     * not limited to specific views, and will handle changes to any views
535     * in the hierarchy of a scene change.
536     *
537     * @return the list of target IDs
538     */
539    @NonNull
540    public List<Integer> getTargetIds() {
541        return mImpl.getTargetIds();
542    }
543
544    /**
545     * Returns the array of target views that this transition limits itself to
546     * tracking and animating. If the array is null for both this method and
547     * {@link #getTargetIds()}, then this transition is
548     * not limited to specific views, and will handle changes to any views
549     * in the hierarchy of a scene change.
550     *
551     * @return the list of target views
552     */
553    @NonNull
554    public List<View> getTargets() {
555        return mImpl.getTargets();
556    }
557
558    /**
559     * Returns the set of property names used stored in the {@link TransitionValues}
560     * object passed into {@link #captureStartValues(TransitionValues)} that
561     * this transition cares about for the purposes of canceling overlapping animations.
562     * When any transition is started on a given scene root, all transitions
563     * currently running on that same scene root are checked to see whether the
564     * properties on which they based their animations agree with the end values of
565     * the same properties in the new transition. If the end values are not equal,
566     * then the old animation is canceled since the new transition will start a new
567     * animation to these new values. If the values are equal, the old animation is
568     * allowed to continue and no new animation is started for that transition.
569     *
570     * <p>A transition does not need to override this method. However, not doing so
571     * will mean that the cancellation logic outlined in the previous paragraph
572     * will be skipped for that transition, possibly leading to artifacts as
573     * old transitions and new transitions on the same targets run in parallel,
574     * animating views toward potentially different end values.</p>
575     *
576     * @return An array of property names as described in the class documentation for
577     * {@link TransitionValues}. The default implementation returns <code>null</code>.
578     */
579    @Nullable
580    public String[] getTransitionProperties() {
581        return mImpl.getTransitionProperties();
582    }
583
584    /**
585     * This method can be called by transitions to get the TransitionValues for
586     * any particular view during the transition-playing process. This might be
587     * necessary, for example, to query the before/after state of related views
588     * for a given transition.
589     */
590    @NonNull
591    public TransitionValues getTransitionValues(@NonNull View view, boolean start) {
592        return mImpl.getTransitionValues(view, start);
593    }
594
595    /**
596     * Removes a listener from the set listening to this animation.
597     *
598     * @param listener the listener to be removed from the current set of
599     *                 listeners for this transition.
600     * @return This transition object.
601     */
602    @NonNull
603    public Transition removeListener(@NonNull TransitionListener listener) {
604        mImpl.removeListener(listener);
605        return this;
606    }
607
608    /**
609     * Removes the given target from the list of targets that this Transition
610     * is interested in animating.
611     *
612     * @param target The target view, must be non-null.
613     * @return Transition The Transition from which the target is removed.
614     * Returning the same object makes it easier to chain calls during
615     * construction, such as
616     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
617     */
618    @NonNull
619    public Transition removeTarget(@NonNull View target) {
620        mImpl.removeTarget(target);
621        return this;
622    }
623
624    /**
625     * Removes the given targetId from the list of ids that this Transition
626     * is interested in animating.
627     *
628     * @param targetId The id of a target view, must be a positive number.
629     * @return The Transition from which the targetId is removed.
630     * Returning the same object makes it easier to chain calls during
631     * construction, such as
632     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
633     */
634    @NonNull
635    public Transition removeTarget(@IdRes int targetId) {
636        mImpl.removeTarget(targetId);
637        return this;
638    }
639
640    @Override
641    public String toString() {
642        return mImpl.toString();
643    }
644
645    /**
646     * A transition listener receives notifications from a transition.
647     * Notifications indicate transition lifecycle events.
648     */
649    public interface TransitionListener extends TransitionInterfaceListener<Transition> {
650
651        /**
652         * Notification about the start of the transition.
653         *
654         * @param transition The started transition.
655         */
656        @Override
657        void onTransitionStart(@NonNull Transition transition);
658
659        /**
660         * Notification about the end of the transition. Canceled transitions
661         * will always notify listeners of both the cancellation and end
662         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
663         * regardless of whether the transition was canceled or played
664         * through to completion.
665         *
666         * @param transition The transition which reached its end.
667         */
668        @Override
669        void onTransitionEnd(@NonNull Transition transition);
670
671        /**
672         * Notification about the cancellation of the transition.
673         * Note that cancel may be called by a parent {@link TransitionSet} on
674         * a child transition which has not yet started. This allows the child
675         * transition to restore state on target objects which was set at
676         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
677         * createAnimator()} time.
678         *
679         * @param transition The transition which was canceled.
680         */
681        @Override
682        void onTransitionCancel(@NonNull Transition transition);
683
684        /**
685         * Notification when a transition is paused.
686         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
687         * a child transition which has not yet started. This allows the child
688         * transition to restore state on target objects which was set at
689         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
690         * createAnimator()} time.
691         *
692         * @param transition The transition which was paused.
693         */
694        @Override
695        void onTransitionPause(@NonNull Transition transition);
696
697        /**
698         * Notification when a transition is resumed.
699         * Note that resume() may be called by a parent {@link TransitionSet} on
700         * a child transition which has not yet started. This allows the child
701         * transition to restore state which may have changed in an earlier call
702         * to {@link #onTransitionPause(Transition)}.
703         *
704         * @param transition The transition which was resumed.
705         */
706        @Override
707        void onTransitionResume(@NonNull Transition transition);
708    }
709
710}
711