1/* This file is auto-generated from BaseFragment.java. DO NOT MODIFY. */ 2 3/* 4 * Copyright (C) 2014 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 7 * in compliance with the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software distributed under the License 12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 13 * or implied. See the License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.support.v17.leanback.app; 17 18import android.os.Bundle; 19import android.support.v17.leanback.R; 20import android.support.v17.leanback.transition.TransitionHelper; 21import android.support.v17.leanback.transition.TransitionListener; 22import android.view.View; 23import android.view.ViewTreeObserver; 24 25import android.support.v17.leanback.util.StateMachine; 26import android.support.v17.leanback.util.StateMachine.State; 27 28import static android.support.v17.leanback.util.StateMachine.*; 29 30/** 31 * @hide 32 */ 33class BaseSupportFragment extends BrandedSupportFragment { 34 35 /** 36 * Condition: {@link TransitionHelper#systemSupportsEntranceTransitions()} is true 37 * Action: none 38 */ 39 private final State STATE_ALLOWED = new State() { 40 @Override 41 public boolean canRun() { 42 return TransitionHelper.systemSupportsEntranceTransitions(); 43 } 44 45 @Override 46 public void run() { 47 mProgressBarManager.show(); 48 } 49 }; 50 51 /** 52 * Condition: {@link #isReadyForPrepareEntranceTransition()} is true 53 * Action: {@link #onEntranceTransitionPrepare()} } 54 */ 55 private final State STATE_PREPARE = new State() { 56 @Override 57 public boolean canRun() { 58 return isReadyForPrepareEntranceTransition(); 59 } 60 61 @Override 62 public void run() { 63 onEntranceTransitionPrepare(); 64 } 65 }; 66 67 /** 68 * Condition: {@link #isReadyForStartEntranceTransition()} is true 69 * Action: {@link #onExecuteEntranceTransition()} } 70 */ 71 private final State STATE_START = new State() { 72 @Override 73 public boolean canRun() { 74 return isReadyForStartEntranceTransition(); 75 } 76 77 @Override 78 public void run() { 79 mProgressBarManager.hide(); 80 onExecuteEntranceTransition(); 81 } 82 }; 83 84 final StateMachine mEnterTransitionStates; 85 86 private Object mEntranceTransition; 87 private final ProgressBarManager mProgressBarManager = new ProgressBarManager(); 88 89 BaseSupportFragment() { 90 mEnterTransitionStates = new StateMachine(); 91 mEnterTransitionStates.addState(STATE_ALLOWED); 92 mEnterTransitionStates.addState(STATE_PREPARE); 93 mEnterTransitionStates.addState(STATE_START); 94 } 95 96 @Override 97 public void onViewCreated(View view, Bundle savedInstanceState) { 98 super.onViewCreated(view, savedInstanceState); 99 performPendingStates(); 100 } 101 102 final void performPendingStates() { 103 mEnterTransitionStates.runPendingStates(); 104 } 105 106 /** 107 * Enables entrance transition.<p> 108 * Entrance transition is the standard slide-in transition that shows rows of data in 109 * browse screen and details screen. 110 * <p> 111 * The method is ignored before LOLLIPOP (API21). 112 * <p> 113 * This method must be called in or 114 * before onCreate(). Typically entrance transition should be enabled when savedInstance is 115 * null so that fragment restored from instanceState does not run an extra entrance transition. 116 * When the entrance transition is enabled, the fragment will make headers and content 117 * hidden initially. 118 * When data of rows are ready, app must call {@link #startEntranceTransition()} to kick off 119 * the transition, otherwise the rows will be invisible forever. 120 * <p> 121 * It is similar to android:windowsEnterTransition and can be considered a late-executed 122 * android:windowsEnterTransition controlled by app. There are two reasons that app needs it: 123 * <li> Workaround the problem that activity transition is not available between launcher and 124 * app. Browse activity must programmatically start the slide-in transition.</li> 125 * <li> Separates DetailsOverviewRow transition from other rows transition. So that 126 * the DetailsOverviewRow transition can be executed earlier without waiting for all rows 127 * to be loaded.</li> 128 * <p> 129 * Transition object is returned by createEntranceTransition(). Typically the app does not need 130 * override the default transition that browse and details provides. 131 */ 132 public void prepareEntranceTransition() { 133 mEnterTransitionStates.runState(STATE_ALLOWED); 134 mEnterTransitionStates.runState(STATE_PREPARE); 135 } 136 137 /** 138 * Return true if entrance transition is enabled and not started yet. 139 * Entrance transition can only be executed once and isEntranceTransitionEnabled() 140 * is reset to false after entrance transition is started. 141 */ 142 boolean isEntranceTransitionEnabled() { 143 // Enabled when passed STATE_ALLOWED in prepareEntranceTransition call. 144 return STATE_ALLOWED.getStatus() == STATUS_EXECUTED; 145 } 146 147 /** 148 * Create entrance transition. Subclass can override to load transition from 149 * resource or construct manually. Typically app does not need to 150 * override the default transition that browse and details provides. 151 */ 152 protected Object createEntranceTransition() { 153 return null; 154 } 155 156 /** 157 * Run entrance transition. Subclass may use TransitionManager to perform 158 * go(Scene) or beginDelayedTransition(). App should not override the default 159 * implementation of browse and details fragment. 160 */ 161 protected void runEntranceTransition(Object entranceTransition) { 162 } 163 164 /** 165 * Callback when entrance transition is prepared. This is when fragment should 166 * stop user input and animations. 167 */ 168 protected void onEntranceTransitionPrepare() { 169 } 170 171 /** 172 * Callback when entrance transition is started. This is when fragment should 173 * stop processing layout. 174 */ 175 protected void onEntranceTransitionStart() { 176 } 177 178 /** 179 * Callback when entrance transition is ended. 180 */ 181 protected void onEntranceTransitionEnd() { 182 } 183 184 /** 185 * Returns true if it is ready to perform {@link #prepareEntranceTransition()}, false otherwise. 186 * Subclass may override and add additional conditions. 187 * @return True if it is ready to perform {@link #prepareEntranceTransition()}, false otherwise. 188 * Subclass may override and add additional conditions. 189 */ 190 boolean isReadyForPrepareEntranceTransition() { 191 return getView() != null; 192 } 193 194 /** 195 * Returns true if it is ready to perform {@link #startEntranceTransition()}, false otherwise. 196 * Subclass may override and add additional conditions. 197 * @return True if it is ready to perform {@link #startEntranceTransition()}, false otherwise. 198 * Subclass may override and add additional conditions. 199 */ 200 boolean isReadyForStartEntranceTransition() { 201 return getView() != null; 202 } 203 204 /** 205 * When fragment finishes loading data, it should call startEntranceTransition() 206 * to execute the entrance transition. 207 * startEntranceTransition() will start transition only if both two conditions 208 * are satisfied: 209 * <li> prepareEntranceTransition() was called.</li> 210 * <li> has not executed entrance transition yet.</li> 211 * <p> 212 * If startEntranceTransition() is called before onViewCreated(), it will be pending 213 * and executed when view is created. 214 */ 215 public void startEntranceTransition() { 216 mEnterTransitionStates.runState(STATE_START); 217 } 218 219 void onExecuteEntranceTransition() { 220 // wait till views get their initial position before start transition 221 final View view = getView(); 222 view.getViewTreeObserver().addOnPreDrawListener( 223 new ViewTreeObserver.OnPreDrawListener() { 224 @Override 225 public boolean onPreDraw() { 226 view.getViewTreeObserver().removeOnPreDrawListener(this); 227 internalCreateEntranceTransition(); 228 if (mEntranceTransition != null) { 229 onEntranceTransitionStart(); 230 runEntranceTransition(mEntranceTransition); 231 } 232 return false; 233 } 234 }); 235 view.invalidate(); 236 } 237 238 void internalCreateEntranceTransition() { 239 mEntranceTransition = createEntranceTransition(); 240 if (mEntranceTransition == null) { 241 return; 242 } 243 TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() { 244 @Override 245 public void onTransitionEnd(Object transition) { 246 mEntranceTransition = null; 247 onEntranceTransitionEnd(); 248 mEnterTransitionStates.resetStatus(); 249 } 250 }); 251 } 252 253 /** 254 * Returns the {@link ProgressBarManager}. 255 */ 256 public final ProgressBarManager getProgressBarManager() { 257 return mProgressBarManager; 258 } 259} 260