1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package androidx.leanback.transition; 15 16 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 17 18 import android.animation.TimeInterpolator; 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.os.Build; 22 import android.transition.AutoTransition; 23 import android.transition.ChangeTransform; 24 import android.transition.Fade; 25 import android.transition.Scene; 26 import android.transition.Transition; 27 import android.transition.TransitionInflater; 28 import android.transition.TransitionManager; 29 import android.transition.TransitionSet; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.view.Window; 33 import android.view.animation.AnimationUtils; 34 35 import androidx.annotation.RestrictTo; 36 37 import java.util.ArrayList; 38 39 /** 40 * Helper for view transitions. 41 * @hide 42 */ 43 @RestrictTo(LIBRARY_GROUP) 44 public final class TransitionHelper { 45 46 public static final int FADE_IN = 0x1; 47 public static final int FADE_OUT = 0x2; 48 49 /** 50 * Returns true if system supports entrance Transition animations. 51 */ systemSupportsEntranceTransitions()52 public static boolean systemSupportsEntranceTransitions() { 53 return Build.VERSION.SDK_INT >= 21; 54 } 55 56 private static class TransitionStub { 57 ArrayList<TransitionListener> mTransitionListeners; 58 TransitionStub()59 TransitionStub() { 60 } 61 } 62 getSharedElementEnterTransition(Window window)63 public static Object getSharedElementEnterTransition(Window window) { 64 if (Build.VERSION.SDK_INT >= 21) { 65 return window.getSharedElementEnterTransition(); 66 } 67 return null; 68 } 69 setSharedElementEnterTransition(Window window, Object transition)70 public static void setSharedElementEnterTransition(Window window, Object transition) { 71 if (Build.VERSION.SDK_INT >= 21) { 72 window.setSharedElementEnterTransition((Transition) transition); 73 } 74 } 75 getSharedElementReturnTransition(Window window)76 public static Object getSharedElementReturnTransition(Window window) { 77 if (Build.VERSION.SDK_INT >= 21) { 78 return window.getSharedElementReturnTransition(); 79 } 80 return null; 81 } 82 setSharedElementReturnTransition(Window window, Object transition)83 public static void setSharedElementReturnTransition(Window window, Object transition) { 84 if (Build.VERSION.SDK_INT >= 21) { 85 window.setSharedElementReturnTransition((Transition) transition); 86 } 87 } 88 getSharedElementExitTransition(Window window)89 public static Object getSharedElementExitTransition(Window window) { 90 if (Build.VERSION.SDK_INT >= 21) { 91 return window.getSharedElementExitTransition(); 92 } 93 return null; 94 } 95 getSharedElementReenterTransition(Window window)96 public static Object getSharedElementReenterTransition(Window window) { 97 if (Build.VERSION.SDK_INT >= 21) { 98 return window.getSharedElementReenterTransition(); 99 } 100 return null; 101 } 102 getEnterTransition(Window window)103 public static Object getEnterTransition(Window window) { 104 if (Build.VERSION.SDK_INT >= 21) { 105 return window.getEnterTransition(); 106 } 107 return null; 108 } 109 setEnterTransition(Window window, Object transition)110 public static void setEnterTransition(Window window, Object transition) { 111 if (Build.VERSION.SDK_INT >= 21) { 112 window.setEnterTransition((Transition) transition); 113 } 114 } 115 getReturnTransition(Window window)116 public static Object getReturnTransition(Window window) { 117 if (Build.VERSION.SDK_INT >= 21) { 118 return window.getReturnTransition(); 119 } 120 return null; 121 } 122 setReturnTransition(Window window, Object transition)123 public static void setReturnTransition(Window window, Object transition) { 124 if (Build.VERSION.SDK_INT >= 21) { 125 window.setReturnTransition((Transition) transition); 126 } 127 } 128 getExitTransition(Window window)129 public static Object getExitTransition(Window window) { 130 if (Build.VERSION.SDK_INT >= 21) { 131 return window.getExitTransition(); 132 } 133 return null; 134 } 135 getReenterTransition(Window window)136 public static Object getReenterTransition(Window window) { 137 if (Build.VERSION.SDK_INT >= 21) { 138 return window.getReenterTransition(); 139 } 140 return null; 141 } 142 createScene(ViewGroup sceneRoot, Runnable r)143 public static Object createScene(ViewGroup sceneRoot, Runnable r) { 144 if (Build.VERSION.SDK_INT >= 19) { 145 Scene scene = new Scene(sceneRoot); 146 scene.setEnterAction(r); 147 return scene; 148 } 149 return r; 150 } 151 createChangeBounds(boolean reparent)152 public static Object createChangeBounds(boolean reparent) { 153 if (Build.VERSION.SDK_INT >= 19) { 154 CustomChangeBounds changeBounds = new CustomChangeBounds(); 155 changeBounds.setReparent(reparent); 156 return changeBounds; 157 } 158 return new TransitionStub(); 159 } 160 createChangeTransform()161 public static Object createChangeTransform() { 162 if (Build.VERSION.SDK_INT >= 21) { 163 return new ChangeTransform(); 164 } 165 return new TransitionStub(); 166 } 167 setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay)168 public static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) { 169 if (Build.VERSION.SDK_INT >= 19) { 170 ((CustomChangeBounds) changeBounds).setStartDelay(view, startDelay); 171 } 172 } 173 setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay)174 public static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) { 175 if (Build.VERSION.SDK_INT >= 19) { 176 ((CustomChangeBounds) changeBounds).setStartDelay(viewId, startDelay); 177 } 178 } 179 setChangeBoundsStartDelay(Object changeBounds, String className, int startDelay)180 public static void setChangeBoundsStartDelay(Object changeBounds, String className, 181 int startDelay) { 182 if (Build.VERSION.SDK_INT >= 19) { 183 ((CustomChangeBounds) changeBounds).setStartDelay(className, startDelay); 184 } 185 } 186 setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay)187 public static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) { 188 if (Build.VERSION.SDK_INT >= 19) { 189 ((CustomChangeBounds) changeBounds).setDefaultStartDelay(startDelay); 190 } 191 } 192 createTransitionSet(boolean sequential)193 public static Object createTransitionSet(boolean sequential) { 194 if (Build.VERSION.SDK_INT >= 19) { 195 TransitionSet set = new TransitionSet(); 196 set.setOrdering(sequential ? TransitionSet.ORDERING_SEQUENTIAL 197 : TransitionSet.ORDERING_TOGETHER); 198 return set; 199 } 200 return new TransitionStub(); 201 } 202 createSlide(int slideEdge)203 public static Object createSlide(int slideEdge) { 204 if (Build.VERSION.SDK_INT >= 19) { 205 SlideKitkat slide = new SlideKitkat(); 206 slide.setSlideEdge(slideEdge); 207 return slide; 208 } 209 return new TransitionStub(); 210 } 211 createScale()212 public static Object createScale() { 213 if (Build.VERSION.SDK_INT >= 21) { 214 return new ChangeTransform(); 215 } 216 if (Build.VERSION.SDK_INT >= 19) { 217 return new Scale(); 218 } 219 return new TransitionStub(); 220 } 221 addTransition(Object transitionSet, Object transition)222 public static void addTransition(Object transitionSet, Object transition) { 223 if (Build.VERSION.SDK_INT >= 19) { 224 ((TransitionSet) transitionSet).addTransition((Transition) transition); 225 } 226 } 227 exclude(Object transition, int targetId, boolean exclude)228 public static void exclude(Object transition, int targetId, boolean exclude) { 229 if (Build.VERSION.SDK_INT >= 19) { 230 ((Transition) transition).excludeTarget(targetId, exclude); 231 } 232 } 233 exclude(Object transition, View targetView, boolean exclude)234 public static void exclude(Object transition, View targetView, boolean exclude) { 235 if (Build.VERSION.SDK_INT >= 19) { 236 ((Transition) transition).excludeTarget(targetView, exclude); 237 } 238 } 239 excludeChildren(Object transition, int targetId, boolean exclude)240 public static void excludeChildren(Object transition, int targetId, boolean exclude) { 241 if (Build.VERSION.SDK_INT >= 19) { 242 ((Transition) transition).excludeChildren(targetId, exclude); 243 } 244 } 245 excludeChildren(Object transition, View targetView, boolean exclude)246 public static void excludeChildren(Object transition, View targetView, boolean exclude) { 247 if (Build.VERSION.SDK_INT >= 19) { 248 ((Transition) transition).excludeChildren(targetView, exclude); 249 } 250 } 251 include(Object transition, int targetId)252 public static void include(Object transition, int targetId) { 253 if (Build.VERSION.SDK_INT >= 19) { 254 ((Transition) transition).addTarget(targetId); 255 } 256 } 257 include(Object transition, View targetView)258 public static void include(Object transition, View targetView) { 259 if (Build.VERSION.SDK_INT >= 19) { 260 ((Transition) transition).addTarget(targetView); 261 } 262 } 263 setStartDelay(Object transition, long startDelay)264 public static void setStartDelay(Object transition, long startDelay) { 265 if (Build.VERSION.SDK_INT >= 19) { 266 ((Transition) transition).setStartDelay(startDelay); 267 } 268 } 269 setDuration(Object transition, long duration)270 public static void setDuration(Object transition, long duration) { 271 if (Build.VERSION.SDK_INT >= 19) { 272 ((Transition) transition).setDuration(duration); 273 } 274 } 275 createAutoTransition()276 public static Object createAutoTransition() { 277 if (Build.VERSION.SDK_INT >= 19) { 278 return new AutoTransition(); 279 } 280 return new TransitionStub(); 281 } 282 createFadeTransition(int fadeMode)283 public static Object createFadeTransition(int fadeMode) { 284 if (Build.VERSION.SDK_INT >= 19) { 285 return new Fade(fadeMode); 286 } 287 return new TransitionStub(); 288 } 289 addTransitionListener(Object transition, final TransitionListener listener)290 public static void addTransitionListener(Object transition, final TransitionListener listener) { 291 if (listener == null) { 292 return; 293 } 294 if (Build.VERSION.SDK_INT >= 19) { 295 Transition t = (Transition) transition; 296 listener.mImpl = new Transition.TransitionListener() { 297 @Override 298 public void onTransitionStart(Transition transition11) { 299 listener.onTransitionStart(transition11); 300 } 301 302 @Override 303 public void onTransitionResume(Transition transition11) { 304 listener.onTransitionResume(transition11); 305 } 306 307 @Override 308 public void onTransitionPause(Transition transition11) { 309 listener.onTransitionPause(transition11); 310 } 311 312 @Override 313 public void onTransitionEnd(Transition transition11) { 314 listener.onTransitionEnd(transition11); 315 } 316 317 @Override 318 public void onTransitionCancel(Transition transition11) { 319 listener.onTransitionCancel(transition11); 320 } 321 }; 322 t.addListener((Transition.TransitionListener) listener.mImpl); 323 } else { 324 TransitionStub stub = (TransitionStub) transition; 325 if (stub.mTransitionListeners == null) { 326 stub.mTransitionListeners = new ArrayList<>(); 327 } 328 stub.mTransitionListeners.add(listener); 329 } 330 } 331 removeTransitionListener(Object transition, TransitionListener listener)332 public static void removeTransitionListener(Object transition, TransitionListener listener) { 333 if (Build.VERSION.SDK_INT >= 19) { 334 if (listener == null || listener.mImpl == null) { 335 return; 336 } 337 Transition t = (Transition) transition; 338 t.removeListener((Transition.TransitionListener) listener.mImpl); 339 listener.mImpl = null; 340 } else { 341 TransitionStub stub = (TransitionStub) transition; 342 if (stub.mTransitionListeners != null) { 343 stub.mTransitionListeners.remove(listener); 344 } 345 } 346 } 347 runTransition(Object scene, Object transition)348 public static void runTransition(Object scene, Object transition) { 349 if (Build.VERSION.SDK_INT >= 19) { 350 TransitionManager.go((Scene) scene, (Transition) transition); 351 } else { 352 TransitionStub transitionStub = (TransitionStub) transition; 353 if (transitionStub != null && transitionStub.mTransitionListeners != null) { 354 for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) { 355 transitionStub.mTransitionListeners.get(i).onTransitionStart(transition); 356 } 357 } 358 Runnable r = ((Runnable) scene); 359 if (r != null) { 360 r.run(); 361 } 362 if (transitionStub != null && transitionStub.mTransitionListeners != null) { 363 for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) { 364 transitionStub.mTransitionListeners.get(i).onTransitionEnd(transition); 365 } 366 } 367 } 368 } 369 setInterpolator(Object transition, Object timeInterpolator)370 public static void setInterpolator(Object transition, Object timeInterpolator) { 371 if (Build.VERSION.SDK_INT >= 19) { 372 ((Transition) transition).setInterpolator((TimeInterpolator) timeInterpolator); 373 } 374 } 375 addTarget(Object transition, View view)376 public static void addTarget(Object transition, View view) { 377 if (Build.VERSION.SDK_INT >= 19) { 378 ((Transition) transition).addTarget(view); 379 } 380 } 381 createDefaultInterpolator(Context context)382 public static Object createDefaultInterpolator(Context context) { 383 if (Build.VERSION.SDK_INT >= 21) { 384 return AnimationUtils.loadInterpolator(context, 385 android.R.interpolator.fast_out_linear_in); 386 } 387 return null; 388 } 389 loadTransition(Context context, int resId)390 public static Object loadTransition(Context context, int resId) { 391 if (Build.VERSION.SDK_INT >= 19) { 392 return TransitionInflater.from(context).inflateTransition(resId); 393 } 394 return new TransitionStub(); 395 } 396 setEnterTransition(android.app.Fragment fragment, Object transition)397 public static void setEnterTransition(android.app.Fragment fragment, Object transition) { 398 if (Build.VERSION.SDK_INT >= 21) { 399 fragment.setEnterTransition((Transition) transition); 400 } 401 } 402 setExitTransition(android.app.Fragment fragment, Object transition)403 public static void setExitTransition(android.app.Fragment fragment, Object transition) { 404 if (Build.VERSION.SDK_INT >= 21) { 405 fragment.setExitTransition((Transition) transition); 406 } 407 } 408 setSharedElementEnterTransition(android.app.Fragment fragment, Object transition)409 public static void setSharedElementEnterTransition(android.app.Fragment fragment, 410 Object transition) { 411 if (Build.VERSION.SDK_INT >= 21) { 412 fragment.setSharedElementEnterTransition((Transition) transition); 413 } 414 } 415 addSharedElement(android.app.FragmentTransaction ft, View view, String transitionName)416 public static void addSharedElement(android.app.FragmentTransaction ft, 417 View view, String transitionName) { 418 if (Build.VERSION.SDK_INT >= 21) { 419 ft.addSharedElement(view, transitionName); 420 } 421 } 422 createFadeAndShortSlide(int edge)423 public static Object createFadeAndShortSlide(int edge) { 424 if (Build.VERSION.SDK_INT >= 21) { 425 return new FadeAndShortSlide(edge); 426 } 427 return new TransitionStub(); 428 } 429 createFadeAndShortSlide(int edge, float distance)430 public static Object createFadeAndShortSlide(int edge, float distance) { 431 if (Build.VERSION.SDK_INT >= 21) { 432 FadeAndShortSlide slide = new FadeAndShortSlide(edge); 433 slide.setDistance(distance); 434 return slide; 435 } 436 return new TransitionStub(); 437 } 438 beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject)439 public static void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) { 440 if (Build.VERSION.SDK_INT >= 21) { 441 Transition transition = (Transition) transitionObject; 442 TransitionManager.beginDelayedTransition(sceneRoot, transition); 443 } 444 } 445 setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup)446 public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) { 447 if (Build.VERSION.SDK_INT >= 21) { 448 viewGroup.setTransitionGroup(transitionGroup); 449 } 450 } 451 setEpicenterCallback(Object transition, final TransitionEpicenterCallback callback)452 public static void setEpicenterCallback(Object transition, 453 final TransitionEpicenterCallback callback) { 454 if (Build.VERSION.SDK_INT >= 21) { 455 if (callback == null) { 456 ((Transition) transition).setEpicenterCallback(null); 457 } else { 458 ((Transition) transition).setEpicenterCallback(new Transition.EpicenterCallback() { 459 @Override 460 public Rect onGetEpicenter(Transition transition11) { 461 return callback.onGetEpicenter(transition11); 462 } 463 }); 464 } 465 } 466 } 467 TransitionHelper()468 private TransitionHelper() { 469 } 470 } 471