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 19c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.content.Context; 20c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.os.Build; 21cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Arakiimport android.support.annotation.LayoutRes; 22cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Arakiimport android.support.annotation.NonNull; 23cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Arakiimport android.support.annotation.Nullable; 24c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.util.SparseArray; 25c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.View; 26c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewGroup; 27c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 28c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki/** 29c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * A scene represents the collection of values that various properties in the 30c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * View hierarchy will have when the scene is applied. A Scene can be 31c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * configured to automatically run a Transition when it is applied, which will 32c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * animate the various property changes that take place during the 33c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * scene change. 34c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 35c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakipublic class Scene { 36c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 37c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki private static SceneStaticsImpl sImpl; 38c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 39c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki static { 40bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki if (Build.VERSION.SDK_INT >= 21) { 41bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki sImpl = new SceneStaticsApi21(); 42bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki } else if (Build.VERSION.SDK_INT >= 19) { 43c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki sImpl = new SceneStaticsKitKat(); 44bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki } else { 45bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki sImpl = new SceneStaticsIcs(); 46c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 47c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 48c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 49c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /* package */ SceneImpl mImpl; 50c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 51c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 52c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Constructs a Scene with no information about how values will change 53c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * when this scene is applied. This constructor might be used when 54c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * a Scene is created with the intention of being dynamically configured, 55c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * through setting {@link #setEnterAction(Runnable)} and possibly 56c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * {@link #setExitAction(Runnable)}. 57c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 58c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param sceneRoot The root of the hierarchy in which scene changes 59c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * and transitions will take place. 60c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 61cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki public Scene(@NonNull ViewGroup sceneRoot) { 62c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl = createSceneImpl(); 63c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.init(sceneRoot); 64c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 65c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 66c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 67c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Constructs a Scene which, when entered, will remove any 68c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * children from the sceneRoot container and add the layout 69c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * object as a new child of that container. 70c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 71c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param sceneRoot The root of the hierarchy in which scene changes 72c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * and transitions will take place. 73c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param layout The view hierarchy of this scene, added as a child 74c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * of sceneRoot when this scene is entered. 75c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 76cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki public Scene(@NonNull ViewGroup sceneRoot, @NonNull View layout) { 77c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl = createSceneImpl(); 78c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.init(sceneRoot, layout); 79c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 80c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 81c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki private Scene(SceneImpl scene) { 82c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl = scene; 83c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 84c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 85c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 86c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Returns a Scene described by the resource file associated with the given 87c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * <code>layoutId</code> parameter. If such a Scene has already been created for 88c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * the given <code>sceneRoot</code>, that same Scene will be returned. 89c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * This caching of layoutId-based scenes enables sharing of common scenes 90c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * between those created in code and those referenced by {@link TransitionManager} 91c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * XML resource files. 92c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 93c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param sceneRoot The root of the hierarchy in which scene changes 94c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * and transitions will take place. 95c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param layoutId The id of a standard layout resource file. 96c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param context The context used in the process of inflating 97c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * the layout resource. 98c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @return The scene for the given root and layout id 99c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 100cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki @NonNull 101cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki public static Scene getSceneForLayout(@NonNull ViewGroup sceneRoot, @LayoutRes int layoutId, 102cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki @NonNull Context context) { 103c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki @SuppressWarnings("unchecked") 104c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki SparseArray<Scene> scenes = 105c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki (SparseArray<Scene>) sceneRoot.getTag(R.id.transition_scene_layoutid_cache); 106c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki if (scenes == null) { 107c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki scenes = new SparseArray<>(); 108c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki sceneRoot.setTag(R.id.transition_scene_layoutid_cache, scenes); 109c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 110c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki Scene scene = scenes.get(layoutId); 111c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki if (scene != null) { 112c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki return scene; 113c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } else { 114c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki scene = new Scene(sImpl.getSceneForLayout(sceneRoot, layoutId, context)); 115c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki scenes.put(layoutId, scene); 116c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki return scene; 117c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 118c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 119c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 120c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki private SceneImpl createSceneImpl() { 121bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki if (Build.VERSION.SDK_INT >= 21) { 122bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki return new SceneApi21(); 123bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki } else if (Build.VERSION.SDK_INT >= 19) { 124c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki return new SceneKitKat(); 125bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki } else { 126bd6c3bc3b3bc69f629b11218fbdd2bf171f74d7dYuichi Araki return new SceneIcs(); 127c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 128c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 129c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 130c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 131c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Gets the root of the scene, which is the root of the view hierarchy 132c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * affected by changes due to this scene, and which will be animated 133c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * when this scene is entered. 134c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 135c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @return The root of the view hierarchy affected by this scene. 136c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 137cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki @NonNull 138c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki public ViewGroup getSceneRoot() { 139c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki return mImpl.getSceneRoot(); 140c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 141c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 142c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 143c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Exits this scene, if it is the current scene 144c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * on the scene's {@link #getSceneRoot() scene root}. The current scene is 145c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * set when {@link #enter() entering} a scene. 146c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Exiting a scene runs the {@link #setExitAction(Runnable) exit action} 147c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * if there is one. 148c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 149c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki public void exit() { 150c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.exit(); 151c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 152c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 153c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 154c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Enters this scene, which entails changing all values that 155c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * are specified by this scene. These may be values associated 156c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * with a layout view group or layout resource file which will 157c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * now be added to the scene root, or it may be values changed by 158c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * an {@link #setEnterAction(Runnable)} enter action}, or a 159c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * combination of the these. No transition will be run when the 160c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * scene is entered. To get transition behavior in scene changes, 161c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * use one of the methods in {@link android.support.transition.TransitionManager} instead. 162c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 163c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki public void enter() { 164c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.enter(); 165c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 166c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 167c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 168c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Scenes that are not defined with layout resources or 169c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * hierarchies, or which need to perform additional steps 170c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * after those hierarchies are changed to, should set an enter 171c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * action, and possibly an exit action as well. An enter action 172c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * will cause Scene to call back into application code to do 173c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * anything else the application needs after transitions have 174c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * captured pre-change values and after any other scene changes 175c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * have been applied, such as the layout (if any) being added to 176c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * the view hierarchy. After this method is called, Transitions will 177c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * be played. 178c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 179c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @param action The runnable whose {@link Runnable#run() run()} method will 180c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * be called when this scene is entered 181c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @see #setExitAction(Runnable) 182c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @see android.support.transition.Scene(android.view.ViewGroup, android.view.ViewGroup) 183c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 184cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki public void setEnterAction(@Nullable Runnable action) { 185c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.setEnterAction(action); 186c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 187c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 188c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki /** 189c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Scenes that are not defined with layout resources or 190c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * hierarchies, or which need to perform additional steps 191c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * after those hierarchies are changed to, should set an enter 192c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * action, and possibly an exit action as well. An exit action 193c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * will cause Scene to call back into application code to do 194c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * anything the application needs to do after applicable transitions have 195c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * captured pre-change values, but before any other scene changes 196c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * have been applied, such as the new layout (if any) being added to 197c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * the view hierarchy. After this method is called, the next scene 198c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * will be entered, including a call to {@link #setEnterAction(Runnable)} 199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * if an enter action is set. 200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * 201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @see #setEnterAction(Runnable) 202c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * @see android.support.transition.Scene(android.view.ViewGroup, android.view.ViewGroup) 203c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */ 204cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki public void setExitAction(@Nullable Runnable action) { 205c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki mImpl.setExitAction(action); 206c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki } 207c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki 208c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki} 209