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.os.Build;
20import android.support.annotation.NonNull;
21import android.support.annotation.Nullable;
22import android.view.ViewGroup;
23
24/**
25 * This class manages the set of transitions that fire when there is a
26 * change of {@link Scene}. To use the manager, add scenes along with
27 * transition objects with calls to {@link #setTransition(Scene, Transition)}
28 * or {@link #setTransition(Scene, Scene, Transition)}. Setting specific
29 * transitions for scene changes is not required; by default, a Scene change
30 * will use {@link AutoTransition} to do something reasonable for most
31 * situations. Specifying other transitions for particular scene changes is
32 * only necessary if the application wants different transition behavior
33 * in these situations.
34 *
35 * <p>Unlike the platform version, this does not support declaration by XML resources.</p>
36 */
37public class TransitionManager {
38
39    private static TransitionManagerStaticsImpl sImpl;
40
41    static {
42        if (Build.VERSION.SDK_INT < 19) {
43            sImpl = new TransitionManagerStaticsIcs();
44        } else {
45            sImpl = new TransitionManagerStaticsKitKat();
46        }
47    }
48
49    private TransitionManagerImpl mImpl;
50
51    public TransitionManager() {
52        if (Build.VERSION.SDK_INT < 19) {
53            mImpl = new TransitionManagerIcs();
54        } else {
55            mImpl = new TransitionManagerKitKat();
56        }
57    }
58
59    /**
60     * Convenience method to simply change to the given scene using
61     * the default transition for TransitionManager.
62     *
63     * @param scene The Scene to change to
64     */
65    public static void go(@NonNull Scene scene) {
66        sImpl.go(scene.mImpl);
67    }
68
69    /**
70     * Convenience method to simply change to the given scene using
71     * the given transition.
72     *
73     * <p>Passing in <code>null</code> for the transition parameter will
74     * result in the scene changing without any transition running, and is
75     * equivalent to calling {@link Scene#exit()} on the scene root's
76     * current scene, followed by {@link Scene#enter()} on the scene
77     * specified by the <code>scene</code> parameter.</p>
78     *
79     * @param scene      The Scene to change to
80     * @param transition The transition to use for this scene change. A
81     *                   value of null causes the scene change to happen with no transition.
82     */
83    public static void go(@NonNull Scene scene, @Nullable Transition transition) {
84        sImpl.go(scene.mImpl, transition == null ? null : transition.mImpl);
85    }
86
87    /**
88     * Convenience method to animate, using the default transition,
89     * to a new scene defined by all changes within the given scene root between
90     * calling this method and the next rendering frame.
91     * Equivalent to calling {@link #beginDelayedTransition(ViewGroup, Transition)}
92     * with a value of <code>null</code> for the <code>transition</code> parameter.
93     *
94     * @param sceneRoot The root of the View hierarchy to run the transition on.
95     */
96    public static void beginDelayedTransition(@NonNull final ViewGroup sceneRoot) {
97        sImpl.beginDelayedTransition(sceneRoot);
98    }
99
100    /**
101     * Convenience method to animate to a new scene defined by all changes within
102     * the given scene root between calling this method and the next rendering frame.
103     * Calling this method causes TransitionManager to capture current values in the
104     * scene root and then post a request to run a transition on the next frame.
105     * At that time, the new values in the scene root will be captured and changes
106     * will be animated. There is no need to create a Scene; it is implied by
107     * changes which take place between calling this method and the next frame when
108     * the transition begins.
109     *
110     * <p>Calling this method several times before the next frame (for example, if
111     * unrelated code also wants to make dynamic changes and run a transition on
112     * the same scene root), only the first call will trigger capturing values
113     * and exiting the current scene. Subsequent calls to the method with the
114     * same scene root during the same frame will be ignored.</p>
115     *
116     * <p>Passing in <code>null</code> for the transition parameter will
117     * cause the TransitionManager to use its default transition.</p>
118     *
119     * @param sceneRoot  The root of the View hierarchy to run the transition on.
120     * @param transition The transition to use for this change. A
121     *                   value of null causes the TransitionManager to use the default transition.
122     */
123    public static void beginDelayedTransition(@NonNull final ViewGroup sceneRoot,
124            @Nullable Transition transition) {
125        sImpl.beginDelayedTransition(sceneRoot, transition == null ? null : transition.mImpl);
126    }
127
128    /**
129     * Sets a specific transition to occur when the given scene is entered.
130     *
131     * @param scene      The scene which, when applied, will cause the given
132     *                   transition to run.
133     * @param transition The transition that will play when the given scene is
134     *                   entered. A value of null will result in the default behavior of
135     *                   using the default transition instead.
136     */
137    public void setTransition(@NonNull Scene scene, @Nullable Transition transition) {
138        mImpl.setTransition(scene.mImpl, transition == null ? null : transition.mImpl);
139    }
140
141    /**
142     * Sets a specific transition to occur when the given pair of scenes is
143     * exited/entered.
144     *
145     * @param fromScene  The scene being exited when the given transition will
146     *                   be run
147     * @param toScene    The scene being entered when the given transition will
148     *                   be run
149     * @param transition The transition that will play when the given scene is
150     *                   entered. A value of null will result in the default behavior of
151     *                   using the default transition instead.
152     */
153    public void setTransition(@NonNull Scene fromScene, @NonNull Scene toScene,
154            @Nullable Transition transition) {
155        mImpl.setTransition(fromScene.mImpl, toScene.mImpl,
156                transition == null ? null : transition.mImpl);
157    }
158
159    /**
160     * Change to the given scene, using the
161     * appropriate transition for this particular scene change
162     * (as specified to the TransitionManager, or the default
163     * if no such transition exists).
164     *
165     * @param scene The Scene to change to
166     */
167    public void transitionTo(@NonNull Scene scene) {
168        mImpl.transitionTo(scene.mImpl);
169    }
170
171}
172