13f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu/* 23f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Copyright (C) 2014 The Android Open Source Project 33f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * 43f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 53f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * in compliance with the License. You may obtain a copy of the License at 63f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * 73f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 83f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * 93f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 103f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 113f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 123f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * the License. 133f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 143f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gupackage android.support.v17.leanback.app; 153f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 1649dff44ccf0cef8fc8130415fd1dae1a69e4c786Dake Guimport android.annotation.SuppressLint; 173f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Guimport android.os.Bundle; 183f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Guimport android.support.v17.leanback.transition.TransitionHelper; 193f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Guimport android.support.v17.leanback.transition.TransitionListener; 20a5a85434f936023043f074fb86eaa6d48f7f6411Dake Guimport android.support.v17.leanback.util.StateMachine; 2189097f67f988ebba714a95e10369665280db0c27Dake Guimport android.support.v17.leanback.util.StateMachine.Condition; 2289097f67f988ebba714a95e10369665280db0c27Dake Guimport android.support.v17.leanback.util.StateMachine.Event; 23a5a85434f936023043f074fb86eaa6d48f7f6411Dake Guimport android.support.v17.leanback.util.StateMachine.State; 243103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.view.View; 253103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.view.ViewTreeObserver; 26a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 273f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu/** 2849dff44ccf0cef8fc8130415fd1dae1a69e4c786Dake Gu * Base class for leanback Fragments. This class is not intended to be subclassed by apps. 293f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 3076c53f6a2152d31a255a36276ada145be5ec474aDake Gu@SuppressWarnings("FragmentNotInstantiable") 3149dff44ccf0cef8fc8130415fd1dae1a69e4c786Dake Gupublic class BaseSupportFragment extends BrandedSupportFragment { 323f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 33a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu /** 3489097f67f988ebba714a95e10369665280db0c27Dake Gu * The start state for all 35a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu */ 3689097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_START = new State("START", true, false); 3789097f67f988ebba714a95e10369665280db0c27Dake Gu 3889097f67f988ebba714a95e10369665280db0c27Dake Gu /** 3989097f67f988ebba714a95e10369665280db0c27Dake Gu * Initial State for ENTRNACE transition. 4089097f67f988ebba714a95e10369665280db0c27Dake Gu */ 4189097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_INIT = new State("ENTRANCE_INIT"); 42684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata 4389097f67f988ebba714a95e10369665280db0c27Dake Gu /** 4489097f67f988ebba714a95e10369665280db0c27Dake Gu * prepareEntranceTransition is just called, but view not ready yet. We can enable the 4589097f67f988ebba714a95e10369665280db0c27Dake Gu * busy spinner. 4689097f67f988ebba714a95e10369665280db0c27Dake Gu */ 4789097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_ON_PREPARED = new State("ENTRANCE_ON_PREPARED", true, false) { 48684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata @Override 49684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata public void run() { 50684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata mProgressBarManager.show(); 51684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata } 52a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu }; 53a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 54a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu /** 5589097f67f988ebba714a95e10369665280db0c27Dake Gu * prepareEntranceTransition is called and main content view to slide in was created, so we can 5689097f67f988ebba714a95e10369665280db0c27Dake Gu * call {@link #onEntranceTransitionPrepare}. Note that we dont set initial content to invisible 5789097f67f988ebba714a95e10369665280db0c27Dake Gu * in this State, the process is very different in subclass, e.g. BrowseSupportFragment hide header 5889097f67f988ebba714a95e10369665280db0c27Dake Gu * views and hide main fragment view in two steps. 59a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu */ 6089097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW = new State( 6189097f67f988ebba714a95e10369665280db0c27Dake Gu "ENTRANCE_ON_PREPARED_ON_CREATEVIEW") { 62a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 6389097f67f988ebba714a95e10369665280db0c27Dake Gu public void run() { 6489097f67f988ebba714a95e10369665280db0c27Dake Gu onEntranceTransitionPrepare(); 65a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 6689097f67f988ebba714a95e10369665280db0c27Dake Gu }; 67a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 6889097f67f988ebba714a95e10369665280db0c27Dake Gu /** 6989097f67f988ebba714a95e10369665280db0c27Dake Gu * execute the entrance transition. 7089097f67f988ebba714a95e10369665280db0c27Dake Gu */ 7189097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_PERFORM = new State("STATE_ENTRANCE_PERFORM") { 72a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 73a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu public void run() { 7489097f67f988ebba714a95e10369665280db0c27Dake Gu mProgressBarManager.hide(); 7589097f67f988ebba714a95e10369665280db0c27Dake Gu onExecuteEntranceTransition(); 76a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 77a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu }; 78a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 79a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu /** 8089097f67f988ebba714a95e10369665280db0c27Dake Gu * execute onEntranceTransitionEnd. 81a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu */ 8289097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_ON_ENDED = new State("ENTRANCE_ON_ENDED") { 83a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 8489097f67f988ebba714a95e10369665280db0c27Dake Gu public void run() { 8589097f67f988ebba714a95e10369665280db0c27Dake Gu onEntranceTransitionEnd(); 86a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 8789097f67f988ebba714a95e10369665280db0c27Dake Gu }; 8889097f67f988ebba714a95e10369665280db0c27Dake Gu 8989097f67f988ebba714a95e10369665280db0c27Dake Gu /** 9089097f67f988ebba714a95e10369665280db0c27Dake Gu * either entrance transition completed or skipped 9189097f67f988ebba714a95e10369665280db0c27Dake Gu */ 9289097f67f988ebba714a95e10369665280db0c27Dake Gu final State STATE_ENTRANCE_COMPLETE = new State("ENTRANCE_COMPLETE", true, false); 9389097f67f988ebba714a95e10369665280db0c27Dake Gu 9489097f67f988ebba714a95e10369665280db0c27Dake Gu /** 9589097f67f988ebba714a95e10369665280db0c27Dake Gu * Event fragment.onCreate() 9689097f67f988ebba714a95e10369665280db0c27Dake Gu */ 9789097f67f988ebba714a95e10369665280db0c27Dake Gu final Event EVT_ON_CREATE = new Event("onCreate"); 9889097f67f988ebba714a95e10369665280db0c27Dake Gu 9989097f67f988ebba714a95e10369665280db0c27Dake Gu /** 10089097f67f988ebba714a95e10369665280db0c27Dake Gu * Event fragment.onViewCreated() 10189097f67f988ebba714a95e10369665280db0c27Dake Gu */ 10289097f67f988ebba714a95e10369665280db0c27Dake Gu final Event EVT_ON_CREATEVIEW = new Event("onCreateView"); 10389097f67f988ebba714a95e10369665280db0c27Dake Gu 10489097f67f988ebba714a95e10369665280db0c27Dake Gu /** 10589097f67f988ebba714a95e10369665280db0c27Dake Gu * Event for {@link #prepareEntranceTransition()} is called. 10689097f67f988ebba714a95e10369665280db0c27Dake Gu */ 10789097f67f988ebba714a95e10369665280db0c27Dake Gu final Event EVT_PREPARE_ENTRANCE = new Event("prepareEntranceTransition"); 10889097f67f988ebba714a95e10369665280db0c27Dake Gu 10989097f67f988ebba714a95e10369665280db0c27Dake Gu /** 11089097f67f988ebba714a95e10369665280db0c27Dake Gu * Event for {@link #startEntranceTransition()} is called. 11189097f67f988ebba714a95e10369665280db0c27Dake Gu */ 11289097f67f988ebba714a95e10369665280db0c27Dake Gu final Event EVT_START_ENTRANCE = new Event("startEntranceTransition"); 11389097f67f988ebba714a95e10369665280db0c27Dake Gu 11489097f67f988ebba714a95e10369665280db0c27Dake Gu /** 11589097f67f988ebba714a95e10369665280db0c27Dake Gu * Event for entrance transition is ended through Transition listener. 11689097f67f988ebba714a95e10369665280db0c27Dake Gu */ 11789097f67f988ebba714a95e10369665280db0c27Dake Gu final Event EVT_ENTRANCE_END = new Event("onEntranceTransitionEnd"); 118a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 11989097f67f988ebba714a95e10369665280db0c27Dake Gu /** 12089097f67f988ebba714a95e10369665280db0c27Dake Gu * Event for skipping entrance transition if not supported. 12189097f67f988ebba714a95e10369665280db0c27Dake Gu */ 12289097f67f988ebba714a95e10369665280db0c27Dake Gu final Condition COND_TRANSITION_NOT_SUPPORTED = new Condition("EntranceTransitionNotSupport") { 123a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 12489097f67f988ebba714a95e10369665280db0c27Dake Gu public boolean canProceed() { 12589097f67f988ebba714a95e10369665280db0c27Dake Gu return !TransitionHelper.systemSupportsEntranceTransitions(); 126a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 127a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu }; 128a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 12989097f67f988ebba714a95e10369665280db0c27Dake Gu final StateMachine mStateMachine = new StateMachine(); 130a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 13199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas Object mEntranceTransition; 13299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas final ProgressBarManager mProgressBarManager = new ProgressBarManager(); 1333f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 13449dff44ccf0cef8fc8130415fd1dae1a69e4c786Dake Gu @SuppressLint("ValidFragment") 135a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu BaseSupportFragment() { 136a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 137a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 1383f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 13989097f67f988ebba714a95e10369665280db0c27Dake Gu public void onCreate(Bundle savedInstanceState) { 14089097f67f988ebba714a95e10369665280db0c27Dake Gu createStateMachineStates(); 14189097f67f988ebba714a95e10369665280db0c27Dake Gu createStateMachineTransitions(); 14289097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.start(); 14389097f67f988ebba714a95e10369665280db0c27Dake Gu super.onCreate(savedInstanceState); 14489097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_ON_CREATE); 145a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 146a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 14789097f67f988ebba714a95e10369665280db0c27Dake Gu void createStateMachineStates() { 14889097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_START); 14989097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_INIT); 15089097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_ON_PREPARED); 15189097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW); 15289097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_PERFORM); 15389097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_ON_ENDED); 15489097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addState(STATE_ENTRANCE_COMPLETE); 15589097f67f988ebba714a95e10369665280db0c27Dake Gu } 15689097f67f988ebba714a95e10369665280db0c27Dake Gu 15789097f67f988ebba714a95e10369665280db0c27Dake Gu void createStateMachineTransitions() { 15889097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_START, STATE_ENTRANCE_INIT, EVT_ON_CREATE); 15989097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_COMPLETE, 16089097f67f988ebba714a95e10369665280db0c27Dake Gu COND_TRANSITION_NOT_SUPPORTED); 16189097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_COMPLETE, 16289097f67f988ebba714a95e10369665280db0c27Dake Gu EVT_ON_CREATEVIEW); 16389097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_ON_PREPARED, 16489097f67f988ebba714a95e10369665280db0c27Dake Gu EVT_PREPARE_ENTRANCE); 16589097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED, 16689097f67f988ebba714a95e10369665280db0c27Dake Gu STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW, 16789097f67f988ebba714a95e10369665280db0c27Dake Gu EVT_ON_CREATEVIEW); 16889097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED, 16989097f67f988ebba714a95e10369665280db0c27Dake Gu STATE_ENTRANCE_PERFORM, 17089097f67f988ebba714a95e10369665280db0c27Dake Gu EVT_START_ENTRANCE); 17189097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW, 17289097f67f988ebba714a95e10369665280db0c27Dake Gu STATE_ENTRANCE_PERFORM); 17389097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_PERFORM, 17489097f67f988ebba714a95e10369665280db0c27Dake Gu STATE_ENTRANCE_ON_ENDED, 17589097f67f988ebba714a95e10369665280db0c27Dake Gu EVT_ENTRANCE_END); 17689097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.addTransition(STATE_ENTRANCE_ON_ENDED, STATE_ENTRANCE_COMPLETE); 17789097f67f988ebba714a95e10369665280db0c27Dake Gu } 17889097f67f988ebba714a95e10369665280db0c27Dake Gu 17989097f67f988ebba714a95e10369665280db0c27Dake Gu @Override 18089097f67f988ebba714a95e10369665280db0c27Dake Gu public void onViewCreated(View view, Bundle savedInstanceState) { 18189097f67f988ebba714a95e10369665280db0c27Dake Gu super.onViewCreated(view, savedInstanceState); 18289097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_ON_CREATEVIEW); 1833f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 1843f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 1853f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 1863f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Enables entrance transition.<p> 1873f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Entrance transition is the standard slide-in transition that shows rows of data in 1883f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * browse screen and details screen. 1893f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <p> 190572ed31d757c2635ea0a5cdd7ec8a33cd16f77b7Dake Gu * The method is ignored before LOLLIPOP (API21). 191572ed31d757c2635ea0a5cdd7ec8a33cd16f77b7Dake Gu * <p> 1923f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * This method must be called in or 1933f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * before onCreate(). Typically entrance transition should be enabled when savedInstance is 1943f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * null so that fragment restored from instanceState does not run an extra entrance transition. 1953f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * When the entrance transition is enabled, the fragment will make headers and content 1963f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * hidden initially. 1973f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * When data of rows are ready, app must call {@link #startEntranceTransition()} to kick off 1983f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * the transition, otherwise the rows will be invisible forever. 1993f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <p> 2003f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * It is similar to android:windowsEnterTransition and can be considered a late-executed 2013f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * android:windowsEnterTransition controlled by app. There are two reasons that app needs it: 2023f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <li> Workaround the problem that activity transition is not available between launcher and 2033f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * app. Browse activity must programmatically start the slide-in transition.</li> 2043f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <li> Separates DetailsOverviewRow transition from other rows transition. So that 2053f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * the DetailsOverviewRow transition can be executed earlier without waiting for all rows 2063f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * to be loaded.</li> 2073f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <p> 2083f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Transition object is returned by createEntranceTransition(). Typically the app does not need 2093f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * override the default transition that browse and details provides. 2103f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2113f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void prepareEntranceTransition() { 21289097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_PREPARE_ENTRANCE); 2133f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2143f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2153f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 2163f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Create entrance transition. Subclass can override to load transition from 2173f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * resource or construct manually. Typically app does not need to 2183f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * override the default transition that browse and details provides. 2193f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2203f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected Object createEntranceTransition() { 2213f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu return null; 2223f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2233f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2243f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 2253f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Run entrance transition. Subclass may use TransitionManager to perform 2263f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * go(Scene) or beginDelayedTransition(). App should not override the default 2273f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * implementation of browse and details fragment. 2283f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2293f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void runEntranceTransition(Object entranceTransition) { 2303f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2313f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2323f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 233902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu * Callback when entrance transition is prepared. This is when fragment should 234902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu * stop user input and animations. 235902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu */ 236902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu protected void onEntranceTransitionPrepare() { 237902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu } 238902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu 239902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu /** 240902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu * Callback when entrance transition is started. This is when fragment should 241902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu * stop processing layout. 2423f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2433f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void onEntranceTransitionStart() { 2443f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2453f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2463f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 2473f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Callback when entrance transition is ended. 2483f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2493f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void onEntranceTransitionEnd() { 2503f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2513f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2523f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 2533f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * When fragment finishes loading data, it should call startEntranceTransition() 2543f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * to execute the entrance transition. 2553f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * startEntranceTransition() will start transition only if both two conditions 2563f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * are satisfied: 2573f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <li> prepareEntranceTransition() was called.</li> 2583f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <li> has not executed entrance transition yet.</li> 2593f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * <p> 2603f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * If startEntranceTransition() is called before onViewCreated(), it will be pending 2613f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * and executed when view is created. 2623f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 2633f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void startEntranceTransition() { 26489097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_START_ENTRANCE); 265a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 266a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 267a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu void onExecuteEntranceTransition() { 2683f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu // wait till views get their initial position before start transition 2693f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu final View view = getView(); 2708b66ca38dbb9f4af7814e7048a14924deb6251a9Dake Gu if (view == null) { 2718b66ca38dbb9f4af7814e7048a14924deb6251a9Dake Gu // fragment view destroyed, transition not needed 2728b66ca38dbb9f4af7814e7048a14924deb6251a9Dake Gu return; 2738b66ca38dbb9f4af7814e7048a14924deb6251a9Dake Gu } 2742a9b6dfcc745e9ebe3697b590d7f5cdd116b0c3fDake Gu view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 2753f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 2763f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public boolean onPreDraw() { 2773f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu view.getViewTreeObserver().removeOnPreDrawListener(this); 2782452cde3b8d7cbe62f6eb2fbcbcf9a02448d6891Dake Gu if (getContext() == null || getView() == null) { 2792a9b6dfcc745e9ebe3697b590d7f5cdd116b0c3fDake Gu // bail out if fragment is destroyed immediately after startEntranceTransition 2802a9b6dfcc745e9ebe3697b590d7f5cdd116b0c3fDake Gu return true; 2812a9b6dfcc745e9ebe3697b590d7f5cdd116b0c3fDake Gu } 2823f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu internalCreateEntranceTransition(); 28389097f67f988ebba714a95e10369665280db0c27Dake Gu onEntranceTransitionStart(); 284902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu if (mEntranceTransition != null) { 285902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu runEntranceTransition(mEntranceTransition); 28689097f67f988ebba714a95e10369665280db0c27Dake Gu } else { 28789097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_ENTRANCE_END); 288902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu } 2893f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu return false; 2903f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2913f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu }); 2923f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu view.invalidate(); 2933f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 2943f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 2953f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu void internalCreateEntranceTransition() { 2963f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu mEntranceTransition = createEntranceTransition(); 2973f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu if (mEntranceTransition == null) { 2983f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu return; 2993f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 3008403619efebe94666c0615c3fc85080a303acf80Dake Gu TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() { 3013f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 3023f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void onTransitionEnd(Object transition) { 3033f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu mEntranceTransition = null; 30489097f67f988ebba714a95e10369665280db0c27Dake Gu mStateMachine.fireEvent(EVT_ENTRANCE_END); 3053f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 3063f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu }); 3073f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 308684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata 309684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata /** 310684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata * Returns the {@link ProgressBarManager}. 31149dff44ccf0cef8fc8130415fd1dae1a69e4c786Dake Gu * @return The {@link ProgressBarManager}. 312684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata */ 313684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata public final ProgressBarManager getProgressBarManager() { 314684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata return mProgressBarManager; 315684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata } 3163f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu} 317