1c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki/*
2c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Copyright (C) 2016 The Android Open Source Project
3c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
4c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
5c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * you may not use this file except in compliance with the License.
6c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * You may obtain a copy of the License at
7c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
8c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
9c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
10c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Unless required by applicable law or agreed to in writing, software
11c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
12c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * See the License for the specific language governing permissions and
14c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * limitations under the License.
15c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */
16c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
17c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakipackage android.support.transition;
18c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
19c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
20c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.support.v4.util.ArrayMap;
21c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.support.v4.view.ViewCompat;
22c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.util.Log;
23c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.View;
24c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewGroup;
25c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewTreeObserver;
26c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
27c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.lang.ref.WeakReference;
28c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.util.ArrayList;
29c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
30c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport static android.support.annotation.RestrictTo.Scope.GROUP_ID;
31c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette
32c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiclass TransitionManagerPort {
33c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    // TODO: how to handle enter/exit?
34c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
35c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static final String[] EMPTY_STRINGS = new String[0];
36c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
37c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static String LOG_TAG = "TransitionManager";
38c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
39c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static TransitionPort sDefaultTransition = new AutoTransitionPort();
40c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
41c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<TransitionPort>>>>
42c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sRunningTransitions = new ThreadLocal<>();
43c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
445bc71ed43cf5336547217c932a5fc5cbb8c618f5Aurimas Liutikas    static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<>();
45c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
46c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ArrayMap<ScenePort, TransitionPort> mSceneTransitions = new ArrayMap<>();
47c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
48c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ArrayMap<ScenePort, ArrayMap<ScenePort, TransitionPort>> mScenePairTransitions =
49c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            new ArrayMap<>();
50c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
51c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ArrayMap<ScenePort, ArrayMap<String, TransitionPort>> mSceneNameTransitions = new ArrayMap<>();
52c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
53c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ArrayMap<String, ArrayMap<ScenePort, TransitionPort>> mNameSceneTransitions = new ArrayMap<>();
54c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
55c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
56c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Gets the current default transition. The initial value is an {@link
57c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * AutoTransition} instance.
58c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
59c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return The current default transition.
60c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @hide pending later changes
61c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #setDefaultTransition(TransitionPort)
62c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
63c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette    @RestrictTo(GROUP_ID)
64c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static TransitionPort getDefaultTransition() {
65c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return sDefaultTransition;
66c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
67c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
68c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
69c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Sets the transition to be used for any scene change for which no
70c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * other transition is explicitly set. The initial value is
71c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * an {@link AutoTransition} instance.
72c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
73c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param transition The default transition to be used for scene changes.
74c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @hide pending later changes
75c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
76c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette    @RestrictTo(GROUP_ID)
77c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void setDefaultTransition(TransitionPort transition) {
78c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        sDefaultTransition = transition;
79c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
80c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
81c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
82c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * This is where all of the work of a transition/scene-change is
83c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * orchestrated. This method captures the start values for the given
84c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transition, exits the current Scene, enters the new scene, captures
85c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the end values for the transition, and finally plays the
86c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * resulting values-populated transition.
87c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
88c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param scene      The scene being entered
89c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param transition The transition to play for this scene change
90c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
91c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static void changeScene(ScenePort scene, TransitionPort transition) {
92c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
93c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        final ViewGroup sceneRoot = scene.getSceneRoot();
94c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
95cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        TransitionPort transitionClone = null;
96cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        if (transition != null) {
97cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki            transitionClone = transition.clone();
98cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki            transitionClone.setSceneRoot(sceneRoot);
99cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        }
100c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
101c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ScenePort oldScene = ScenePort.getCurrentScene(sceneRoot);
102c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (oldScene != null && oldScene.isCreatedFromLayoutResource()) {
103c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            transitionClone.setCanRemoveViews(true);
104c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
105c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
106c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        sceneChangeSetup(sceneRoot, transitionClone);
107c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
108c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        scene.enter();
109c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
110c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        sceneChangeRunTransition(sceneRoot, transitionClone);
111c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
112c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1135bc71ed43cf5336547217c932a5fc5cbb8c618f5Aurimas Liutikas    static ArrayMap<ViewGroup, ArrayList<TransitionPort>> getRunningTransitions() {
114c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        WeakReference<ArrayMap<ViewGroup, ArrayList<TransitionPort>>> runningTransitions =
115c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                sRunningTransitions.get();
116c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (runningTransitions == null || runningTransitions.get() == null) {
117c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ArrayMap<ViewGroup, ArrayList<TransitionPort>> transitions = new ArrayMap<>();
118c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            runningTransitions = new WeakReference<>(transitions);
119c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sRunningTransitions.set(runningTransitions);
120c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
121c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return runningTransitions.get();
122c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
123c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
124c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
125c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final TransitionPort transition) {
126c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (transition != null && sceneRoot != null) {
127c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            MultiListener listener = new MultiListener(transition, sceneRoot);
128c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sceneRoot.addOnAttachStateChangeListener(listener);
129c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sceneRoot.getViewTreeObserver().addOnPreDrawListener(listener);
130c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
131c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
132c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
133c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static void sceneChangeSetup(ViewGroup sceneRoot, TransitionPort transition) {
134c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
135c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        // Capture current values
136c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayList<TransitionPort> runningTransitions = getRunningTransitions().get(sceneRoot);
137c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
138c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (runningTransitions != null && runningTransitions.size() > 0) {
139c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            for (TransitionPort runningTransition : runningTransitions) {
140feda490114a23e64dba591f1e2589723a1a12660Yuichi Araki                runningTransition.pause(sceneRoot);
141c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
142c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
143c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
144c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (transition != null) {
145c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            transition.captureValues(sceneRoot, true);
146c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
147c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
148c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        // Notify previous scene that it is being exited
149c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ScenePort previousScene = ScenePort.getCurrentScene(sceneRoot);
150c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (previousScene != null) {
151c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            previousScene.exit();
152c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
153c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
154c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
155c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static void go(ScenePort scene) {
156c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        changeScene(scene, sDefaultTransition);
157c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
158c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
159c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static void go(ScenePort scene, TransitionPort transition) {
160c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        changeScene(scene, transition);
161c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
162c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
163c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static void beginDelayedTransition(final ViewGroup sceneRoot) {
164c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        beginDelayedTransition(sceneRoot, null);
165c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
166c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
167c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static void beginDelayedTransition(final ViewGroup sceneRoot,
168c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            TransitionPort transition) {
169c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (!sPendingTransitions.contains(sceneRoot) && ViewCompat.isLaidOut(sceneRoot)) {
170c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (TransitionPort.DBG) {
171c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                Log.d(LOG_TAG, "beginDelayedTransition: root, transition = " +
172c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                        sceneRoot + ", " + transition);
173c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
174c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sPendingTransitions.add(sceneRoot);
175c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (transition == null) {
176c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                transition = sDefaultTransition;
177c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
178c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final TransitionPort transitionClone = transition.clone();
179c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sceneChangeSetup(sceneRoot, transitionClone);
180c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ScenePort.setCurrentScene(sceneRoot, null);
181c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sceneChangeRunTransition(sceneRoot, transitionClone);
182c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
183c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
184c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
185c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void setTransition(ScenePort scene, TransitionPort transition) {
186c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mSceneTransitions.put(scene, transition);
187c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
188c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
189c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void setTransition(ScenePort fromScene, ScenePort toScene, TransitionPort transition) {
190c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayMap<ScenePort, TransitionPort> sceneTransitionMap = mScenePairTransitions.get(toScene);
191c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (sceneTransitionMap == null) {
192c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sceneTransitionMap = new ArrayMap<>();
193c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mScenePairTransitions.put(toScene, sceneTransitionMap);
194c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
195c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        sceneTransitionMap.put(fromScene, transition);
196c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
197c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
198c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Returns the Transition for the given scene being entered. The result
200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * depends not only on the given scene, but also the scene which the
201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * {@link ScenePort#getSceneRoot() sceneRoot} of the Scene is currently in.
202c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
203c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param scene The scene being entered
204c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return The Transition to be used for the given scene change. If no
205c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Transition was specified for this scene change, the default transition
206c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * will be used instead.
207c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
208c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private TransitionPort getTransition(ScenePort scene) {
209c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        TransitionPort transition;
210c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup sceneRoot = scene.getSceneRoot();
211c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (sceneRoot != null) {
212c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // TODO: cached in Scene instead? long-term, cache in View itself
213c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ScenePort currScene = ScenePort.getCurrentScene(sceneRoot);
214c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (currScene != null) {
215c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                ArrayMap<ScenePort, TransitionPort> sceneTransitionMap = mScenePairTransitions
216c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                        .get(scene);
217c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (sceneTransitionMap != null) {
218c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    transition = sceneTransitionMap.get(currScene);
219c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    if (transition != null) {
220c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                        return transition;
221c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    }
222c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
223c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
224c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
225c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        transition = mSceneTransitions.get(scene);
226c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return (transition != null) ? transition : sDefaultTransition;
227c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
228c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
229c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
230c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Retrieve the transition from a named scene to a target defined scene if one has been
231c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * associated with this TransitionManager.
232c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
233c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>A named scene is an indirect link for a transition. Fundamentally a named
234c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene represents a potentially arbitrary intersection point of two otherwise independent
235c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
236c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
237c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * In this way applications may define an API for more sophisticated transitions between
238c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * caller and called activities very similar to the way that <code>Intent</code> extras
239c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * define APIs for arguments and data propagation between activities.</p>
240c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
241c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param fromName Named scene that this transition corresponds to
242c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param toScene  Target scene that this transition will move to
243c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return Transition corresponding to the given fromName and toScene or null
244c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * if no association exists in this TransitionManager
245c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #setTransition(String, ScenePort, TransitionPort)
246c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
247c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public TransitionPort getNamedTransition(String fromName, ScenePort toScene) {
248c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayMap<ScenePort, TransitionPort> m = mNameSceneTransitions.get(fromName);
249c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (m != null) {
250c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return m.get(toScene);
251c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
252c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
253c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
254c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
255c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ;
256c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
257c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
258c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Retrieve the transition from a defined scene to a target named scene if one has been
259c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * associated with this TransitionManager.
260c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
261c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>A named scene is an indirect link for a transition. Fundamentally a named
262c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene represents a potentially arbitrary intersection point of two otherwise independent
263c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
264c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
265c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * In this way applications may define an API for more sophisticated transitions between
266c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * caller and called activities very similar to the way that <code>Intent</code> extras
267c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * define APIs for arguments and data propagation between activities.</p>
268c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
269c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param fromScene Scene that this transition starts from
270c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param toName    Name of the target scene
271c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return Transition corresponding to the given fromScene and toName or null
272c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * if no association exists in this TransitionManager
273c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
274c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public TransitionPort getNamedTransition(ScenePort fromScene, String toName) {
275c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayMap<String, TransitionPort> m = mSceneNameTransitions.get(fromScene);
276c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (m != null) {
277c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return m.get(toName);
278c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
279c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
280c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
281c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
282c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
283c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Retrieve the supported target named scenes when transitioning away from the given scene.
284c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
285c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>A named scene is an indirect link for a transition. Fundamentally a named
286c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene represents a potentially arbitrary intersection point of two otherwise independent
287c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
288c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
289c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * In this way applications may define an API for more sophisticated transitions between
290c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * caller and called activities very similar to the way that <code>Intent</code> extras
291c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * define APIs for arguments and data propagation between activities.</p>
292c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
293c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param fromScene Scene to transition from
294c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return An array of Strings naming each supported transition starting from
295c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <code>fromScene</code>. If no transitions to a named scene from the given
296c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene are supported this function will return a String[] of length 0.
297c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #setTransition(ScenePort, String, TransitionPort)
298c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
299c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public String[] getTargetSceneNames(ScenePort fromScene) {
300c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        final ArrayMap<String, TransitionPort> m = mSceneNameTransitions.get(fromScene);
301c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (m == null) {
302c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return EMPTY_STRINGS;
303c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
304c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        final int count = m.size();
305c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        final String[] result = new String[count];
306c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        for (int i = 0; i < count; i++) {
307c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            result[i] = m.keyAt(i);
308c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
309c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return result;
310c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
311c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
312c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
313c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Set a transition from a specific scene to a named scene.
314c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
315c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>A named scene is an indirect link for a transition. Fundamentally a named
316c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene represents a potentially arbitrary intersection point of two otherwise independent
317c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
318c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
319c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * In this way applications may define an API for more sophisticated transitions between
320c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * caller and called activities very similar to the way that <code>Intent</code> extras
321c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * define APIs for arguments and data propagation between activities.</p>
322c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
323c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param fromScene  Scene to transition from
324c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param toName     Named scene to transition to
325c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param transition Transition to use
326c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #getTargetSceneNames(ScenePort)
327c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
328c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void setTransition(ScenePort fromScene, String toName, TransitionPort transition) {
329c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayMap<String, TransitionPort> m = mSceneNameTransitions.get(fromScene);
330c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (m == null) {
331c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            m = new ArrayMap<>();
332c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mSceneNameTransitions.put(fromScene, m);
333c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        m.put(toName, transition);
335c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
338c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Set a transition from a named scene to a concrete scene.
339c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
340c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>A named scene is an indirect link for a transition. Fundamentally a named
341c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * scene represents a potentially arbitrary intersection point of two otherwise independent
342c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
343c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
344c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * In this way applications may define an API for more sophisticated transitions between
345c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * caller and called activities very similar to the way that <code>Intent</code> extras
346c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * define APIs for arguments and data propagation between activities.</p>
347c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
348c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param fromName   Named scene to transition from
349c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param toScene    Scene to transition to
350c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param transition Transition to use
351c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #getNamedTransition(String, ScenePort)
352c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
353c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void setTransition(String fromName, ScenePort toScene, TransitionPort transition) {
354c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayMap<ScenePort, TransitionPort> m = mNameSceneTransitions.get(fromName);
355c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (m == null) {
356c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            m = new ArrayMap<>();
357c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mNameSceneTransitions.put(fromName, m);
358c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
359c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        m.put(toScene, transition);
360c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
361c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
362c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void transitionTo(ScenePort scene) {
363c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        // Auto transition if there is no transition declared for the Scene, but there is
364c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        // a root or parent view
365c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        changeScene(scene, getTransition(scene));
366c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
367c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
368c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
369c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * This private utility class is used to listen for both OnPreDraw and
370c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OnAttachStateChange events. OnPreDraw events are the main ones we care
371c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * about since that's what triggers the transition to take place.
372c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OnAttachStateChange events are also important in case the view is removed
373c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * from the hierarchy before the OnPreDraw event takes place; it's used to
374c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * clean up things since the OnPreDraw listener didn't get called in time.
375c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
376c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    private static class MultiListener implements ViewTreeObserver.OnPreDrawListener,
377c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            View.OnAttachStateChangeListener {
378c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
379c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        TransitionPort mTransition;
380c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
381c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup mSceneRoot;
382c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
383c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        MultiListener(TransitionPort transition, ViewGroup sceneRoot) {
384c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mTransition = transition;
385c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mSceneRoot = sceneRoot;
386c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
387c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
388c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        private void removeListeners() {
389c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
390c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mSceneRoot.removeOnAttachStateChangeListener(this);
391c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
392c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
393c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
394c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void onViewAttachedToWindow(View v) {
395c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
396c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
397c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
398c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void onViewDetachedFromWindow(View v) {
399c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            removeListeners();
400c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
401c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sPendingTransitions.remove(mSceneRoot);
402c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ArrayList<TransitionPort> runningTransitions = getRunningTransitions().get(mSceneRoot);
403c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (runningTransitions != null && runningTransitions.size() > 0) {
404c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                for (TransitionPort runningTransition : runningTransitions) {
405feda490114a23e64dba591f1e2589723a1a12660Yuichi Araki                    runningTransition.resume(mSceneRoot);
406c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
407c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
408c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mTransition.clearValues(true);
409c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
410c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
411c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
412c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public boolean onPreDraw() {
413c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            removeListeners();
414c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            sPendingTransitions.remove(mSceneRoot);
415c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // Add to running list, handle end to remove it
416c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final ArrayMap<ViewGroup, ArrayList<TransitionPort>> runningTransitions =
417c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    getRunningTransitions();
418c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ArrayList<TransitionPort> currentTransitions = runningTransitions.get(mSceneRoot);
419c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ArrayList<TransitionPort> previousRunningTransitions = null;
420c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (currentTransitions == null) {
421c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                currentTransitions = new ArrayList<>();
422c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                runningTransitions.put(mSceneRoot, currentTransitions);
423c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            } else if (currentTransitions.size() > 0) {
424c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                previousRunningTransitions = new ArrayList<>(currentTransitions);
425c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
426c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            currentTransitions.add(mTransition);
427c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mTransition.addListener(new TransitionPort.TransitionListenerAdapter() {
428c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                @Override
429c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                public void onTransitionEnd(TransitionPort transition) {
430c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    ArrayList<TransitionPort> currentTransitions =
431c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                            runningTransitions.get(mSceneRoot);
432c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    currentTransitions.remove(transition);
433c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
434c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            });
435c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mTransition.captureValues(mSceneRoot, false);
436c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (previousRunningTransitions != null) {
437c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                for (TransitionPort runningTransition : previousRunningTransitions) {
438feda490114a23e64dba591f1e2589723a1a12660Yuichi Araki                    runningTransition.resume(mSceneRoot);
439c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
440c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
441c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mTransition.playTransition(mSceneRoot);
442c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
443c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return true;
444c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
445c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
446c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki}
447