1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.transition.cts; 17 18 import static com.android.compatibility.common.util.CtsMockitoUtils.within; 19 20 import static org.hamcrest.CoreMatchers.allOf; 21 import static org.hamcrest.Matchers.greaterThanOrEqualTo; 22 import static org.hamcrest.Matchers.lessThan; 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertSame; 28 import static org.junit.Assert.assertThat; 29 import static org.junit.Assert.assertTrue; 30 import static org.junit.Assert.fail; 31 import static org.mockito.Matchers.any; 32 import static org.mockito.Matchers.eq; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 38 import android.animation.Animator; 39 import android.graphics.Rect; 40 import android.os.SystemClock; 41 import android.support.test.filters.MediumTest; 42 import android.support.test.runner.AndroidJUnit4; 43 import android.transition.ArcMotion; 44 import android.transition.AutoTransition; 45 import android.transition.ChangeBounds; 46 import android.transition.CircularPropagation; 47 import android.transition.PathMotion; 48 import android.transition.Scene; 49 import android.transition.Transition; 50 import android.transition.Transition.EpicenterCallback; 51 import android.transition.Transition.TransitionListener; 52 import android.transition.TransitionListenerAdapter; 53 import android.transition.TransitionManager; 54 import android.transition.TransitionPropagation; 55 import android.transition.TransitionValues; 56 import android.view.View; 57 import android.view.ViewGroup; 58 import android.view.animation.AccelerateInterpolator; 59 import android.widget.ImageView; 60 import android.widget.RelativeLayout; 61 import android.widget.TextView; 62 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 66 import java.util.HashMap; 67 import java.util.concurrent.CountDownLatch; 68 import java.util.concurrent.TimeUnit; 69 70 @MediumTest 71 @RunWith(AndroidJUnit4.class) 72 public class TransitionTest extends BaseTransitionTest { 73 @Test 74 public void testAddListener() throws Throwable { 75 startTransition(R.layout.scene1); 76 waitForStart(); 77 78 final Transition.TransitionListener listener2 = mock(Transition.TransitionListener.class); 79 80 mActivityRule.runOnUiThread(() -> { 81 AutoTransition autoTransition = new AutoTransition(); 82 autoTransition.setDuration(100); 83 autoTransition.addListener(listener2); 84 Scene scene = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, mActivity); 85 TransitionManager.go(scene, autoTransition); 86 }); 87 88 waitForStart(listener2); 89 90 verify(mListener, times(1)).onTransitionPause(any()); 91 verify(mListener, times(1)).onTransitionResume(any()); 92 verify(mListener, never()).onTransitionCancel(any()); 93 verify(mListener, never()).onTransitionEnd(any()); 94 verify(mListener, times(1)).onTransitionStart(any()); 95 96 verify(listener2, never()).onTransitionPause(any()); 97 verify(listener2, never()).onTransitionResume(any()); 98 verify(listener2, never()).onTransitionCancel(any()); 99 verify(listener2, never()).onTransitionEnd(any()); 100 verify(listener2, times(1)).onTransitionStart(any()); 101 endTransition(); 102 } 103 104 @Test 105 public void testRemoveListener() throws Throwable { 106 startTransition(R.layout.scene1); 107 waitForStart(); 108 109 mActivityRule.runOnUiThread(() -> mTransition.removeListener(mListener)); 110 111 SystemClock.sleep(250); 112 verify(mListener, never()).onTransitionEnd(any()); 113 } 114 115 @Test 116 public void testAddTargetId() throws Throwable { 117 enterScene(R.layout.scene4); 118 assertNotNull(mTransition.getTargetIds()); 119 assertTrue(mTransition.getTargetIds().isEmpty()); 120 mTransition.addTarget(R.id.holder); 121 mTransition.addTarget(R.id.hello); 122 assertEquals(2, mTransition.getTargetIds().size()); 123 startTransition(R.layout.scene1); 124 assertEquals(1, mTargets.size()); 125 assertEquals(R.id.hello, mTargets.get(0).getId()); 126 endTransition(); 127 } 128 129 @Test 130 public void testRemoveTargetId() throws Throwable { 131 enterScene(R.layout.scene4); 132 mTransition.addTarget(R.id.holder); 133 mTransition.addTarget(R.id.hello); 134 mTransition.addTarget(R.id.redSquare); 135 assertEquals(3, mTransition.getTargetIds().size()); 136 mTransition.removeTarget(0); // nothing should happen 137 mTransition.removeTarget(R.id.redSquare); 138 assertEquals(2, mTransition.getTargetIds().size()); 139 140 startTransition(R.layout.scene1); 141 assertEquals(1, mTargets.size()); 142 assertEquals(R.id.hello, mTargets.get(0).getId()); 143 endTransition(); 144 } 145 146 @Test 147 public void testAddTargetClass() throws Throwable { 148 enterScene(R.layout.scene4); 149 assertNull(mTransition.getTargetTypes()); 150 mTransition.addTarget(RelativeLayout.class); 151 mTransition.addTarget(TextView.class); 152 assertEquals(2, mTransition.getTargetTypes().size()); 153 startTransition(R.layout.scene1); 154 assertEquals(1, mTargets.size()); 155 assertTrue(mTargets.get(0) instanceof TextView); 156 endTransition(); 157 } 158 159 @Test 160 public void testRemoveTargetClass() throws Throwable { 161 enterScene(R.layout.scene4); 162 mTransition.addTarget(TextView.class); 163 mTransition.addTarget(View.class); 164 mTransition.addTarget(RelativeLayout.class); 165 assertEquals(3, mTransition.getTargetTypes().size()); 166 mTransition.removeTarget(ImageView.class); // should do nothing 167 mTransition.removeTarget(View.class); 168 assertEquals(2, mTransition.getTargetTypes().size()); 169 startTransition(R.layout.scene1); 170 assertEquals(1, mTargets.size()); 171 assertTrue(mTargets.get(0) instanceof TextView); 172 endTransition(); 173 } 174 175 @Test 176 public void testAddTargetView() throws Throwable { 177 enterScene(R.layout.scene1); 178 179 final View[] target = new View[1]; 180 mActivityRule.runOnUiThread(() -> target[0] = mActivity.findViewById(R.id.hello)); 181 mTransition.addTarget(target[0]); 182 assertEquals(1, mTransition.getTargets().size()); 183 mActivityRule.runOnUiThread(() -> { 184 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition); 185 target[0].setVisibility(View.GONE); 186 }); 187 waitForStart(); 188 assertEquals(1, mTargets.size()); 189 assertEquals(target[0], mTargets.get(0)); 190 endTransition(); 191 } 192 193 @Test 194 public void testRemoveTargetView() throws Throwable { 195 enterScene(R.layout.scene1); 196 197 final View[] target = new View[3]; 198 mActivityRule.runOnUiThread(() -> { 199 target[0] = mActivity.findViewById(R.id.hello); 200 target[1] = mActivity.findViewById(R.id.greenSquare); 201 target[2] = mActivity.findViewById(R.id.redSquare); 202 }); 203 204 mTransition.addTarget(target[0]); 205 mTransition.addTarget(target[1]); 206 assertEquals(2, mTransition.getTargets().size()); 207 mTransition.removeTarget(target[2]); // should do nothing 208 mTransition.removeTarget(target[1]); 209 assertEquals(1, mTransition.getTargets().size()); 210 mActivityRule.runOnUiThread(() -> { 211 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition); 212 target[0].setVisibility(View.GONE); 213 }); 214 waitForStart(); 215 assertEquals(1, mTargets.size()); 216 assertEquals(target[0], mTargets.get(0)); 217 endTransition(); 218 } 219 220 @Test 221 public void testAddTargetName() throws Throwable { 222 enterScene(R.layout.scene4); 223 assertNull(mTransition.getTargetNames()); 224 mTransition.addTarget("red"); 225 mTransition.addTarget("holder"); 226 assertEquals(2, mTransition.getTargetNames().size()); 227 assertEquals(0, mTargets.size()); 228 startTransition(R.layout.scene2); 229 assertEquals(1, mTargets.size()); 230 assertEquals(R.id.redSquare, mTargets.get(0).getId()); 231 endTransition(); 232 } 233 234 @Test 235 public void testRemoveTargetName() throws Throwable { 236 enterScene(R.layout.scene4); 237 mTransition.addTarget("holder"); 238 mTransition.addTarget("red"); 239 mTransition.addTarget("green"); 240 assertEquals(3, mTransition.getTargetNames().size()); 241 mTransition.removeTarget("purple"); // should do nothing 242 // try to force a different String instance 243 String greenName = new StringBuilder("gre").append("en").toString(); 244 mTransition.removeTarget(greenName); 245 assertEquals(2, mTransition.getTargetNames().size()); 246 startTransition(R.layout.scene1); 247 assertEquals(1, mTargets.size()); 248 assertEquals(R.id.redSquare, mTargets.get(0).getId()); 249 endTransition(); 250 } 251 252 @Test 253 public void testIsTransitionRequired() throws Throwable { 254 enterScene(R.layout.scene1); 255 mTransition = new NotRequiredTransition(); 256 assertFalse(mTransition.isTransitionRequired(null, null)); 257 resetListener(); 258 mActivityRule.runOnUiThread(() -> { 259 TransitionManager.beginDelayedTransition(mSceneRoot, mTransition); 260 mActivity.findViewById(R.id.hello).setVisibility(View.GONE); 261 }); 262 waitForStart(); 263 assertEquals(0, mTargets.size()); 264 endTransition(); 265 } 266 267 @Test 268 public void testCanRemoveViews() throws Throwable { 269 enterScene(R.layout.scene1); 270 assertFalse(mTransition.canRemoveViews()); 271 mTransition.addListener(new TransitionListener() { 272 @Override 273 public void onTransitionStart(Transition transition) { 274 assertTrue(transition.canRemoveViews()); 275 } 276 277 @Override 278 public void onTransitionEnd(Transition transition) { 279 } 280 281 @Override 282 public void onTransitionCancel(Transition transition) { 283 } 284 285 @Override 286 public void onTransitionPause(Transition transition) { 287 } 288 289 @Override 290 public void onTransitionResume(Transition transition) { 291 } 292 }); 293 startTransition(R.layout.scene2); 294 } 295 296 @Test 297 public void testExcludeChildrenView() throws Throwable { 298 View layout1 = loadLayout(R.layout.scene1); 299 Scene scene1 = loadScene(layout1); 300 enterScene(scene1); 301 View holder1 = layout1.findViewById(R.id.holder); 302 mTransition.excludeChildren(holder1, true); 303 View layout2 = loadLayout(R.layout.scene2); 304 Scene scene2 = loadScene(layout2); 305 View holder2 = layout2.findViewById(R.id.holder); 306 mTransition.excludeChildren(holder2, true); 307 startTransition(scene2); 308 // Should already be ended, since no children are transitioning 309 verify(mListener, times(1)).onTransitionEnd(any()); 310 311 mTransition.excludeChildren(holder1, false); // remove it 312 mTransition.excludeChildren(holder2, false); // remove it 313 resetListener(); 314 startTransition(scene1); 315 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 316 endTransition(); 317 } 318 319 @Test 320 public void testExcludeChildrenId() throws Throwable { 321 enterScene(R.layout.scene1); 322 mTransition.excludeChildren(R.id.holder, true); 323 startTransition(R.layout.scene2); 324 // Should already be ended, since no children are transitioning 325 verify(mListener, times(1)).onTransitionEnd(any()); 326 327 resetListener(); 328 mTransition.excludeChildren(R.id.holder, false); // remove it 329 startTransition(R.layout.scene1); 330 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 331 endTransition(); 332 } 333 334 @Test 335 public void testExcludeChildrenClass() throws Throwable { 336 enterScene(R.layout.scene1); 337 mTransition.excludeChildren(RelativeLayout.class, true); 338 startTransition(R.layout.scene2); 339 // Should already be ended, since no children are transitioning 340 verify(mListener, times(1)).onTransitionEnd(any()); 341 342 resetListener(); 343 mTransition.excludeChildren(RelativeLayout.class, false); // remove it 344 startTransition(R.layout.scene1); 345 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 346 endTransition(); 347 } 348 349 @Test 350 public void testExcludeTargetView() throws Throwable { 351 View layout1 = loadLayout(R.layout.scene1); 352 Scene scene1 = loadScene(layout1); 353 enterScene(R.layout.scene1); 354 View redSquare1 = layout1.findViewById(R.id.redSquare); 355 mTransition.excludeTarget(redSquare1, true); 356 startTransition(R.layout.scene7); 357 waitForEnd(600); 358 359 mTransition.excludeTarget(redSquare1, false); // remove it 360 resetListener(); 361 startTransition(scene1); 362 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 363 endTransition(); 364 } 365 366 @Test 367 public void testExcludeTargetId() throws Throwable { 368 enterScene(R.layout.scene1); 369 mTransition.excludeTarget(R.id.redSquare, true); 370 startTransition(R.layout.scene7); 371 // Should already be ended, since no children are transitioning 372 verify(mListener, times(1)).onTransitionEnd(any()); 373 374 resetListener(); 375 mTransition.excludeTarget(R.id.redSquare, false); // remove it 376 startTransition(R.layout.scene1); 377 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 378 endTransition(); 379 } 380 381 @Test 382 public void testExcludeTargetClass() throws Throwable { 383 enterScene(R.layout.scene1); 384 mTransition.excludeTarget(TextView.class, true); 385 startTransition(R.layout.scene3); 386 // Should already be ended, since no children are transitioning 387 verify(mListener, times(1)).onTransitionEnd(any()); 388 389 resetListener(); 390 mTransition.excludeTarget(TextView.class, false); // remove it 391 startTransition(R.layout.scene1); 392 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 393 endTransition(); 394 } 395 396 @Test 397 public void testExcludeTargetName() throws Throwable { 398 enterScene(R.layout.scene1); 399 mTransition.excludeTarget("hello", true); 400 startTransition(R.layout.scene3); 401 // Should already be ended, since no children are transitioning 402 verify(mListener, times(1)).onTransitionEnd(any()); 403 404 resetListener(); 405 mTransition.excludeTarget("hello", false); // remove it 406 startTransition(R.layout.scene1); 407 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 408 endTransition(); 409 } 410 411 @Test 412 public void testDuration() throws Throwable { 413 assertEquals(-1, mTransition.getDuration()); 414 enterScene(R.layout.scene1); 415 mTransition.setDuration(500); 416 assertEquals(500, mTransition.getDuration()); 417 DurationListener durationListener = new DurationListener(); 418 mTransition.addListener(durationListener); 419 startTransition(R.layout.scene3); 420 waitForEnd(800); 421 assertThat(durationListener.getDuration(), 422 allOf(greaterThanOrEqualTo(500L), lessThan(900L))); 423 } 424 425 @Test 426 public void testEpicenter() throws Throwable { 427 assertNull(mTransition.getEpicenter()); 428 EpicenterCallback callback = new EpicenterCallback() { 429 @Override 430 public Rect onGetEpicenter(Transition transition) { 431 return new Rect(0, 0, 1, 1); 432 } 433 }; 434 mTransition.setEpicenterCallback(callback); 435 assertSame(callback, mTransition.getEpicenterCallback()); 436 assertEquals(new Rect(0, 0, 1, 1), mTransition.getEpicenter()); 437 } 438 439 @Test 440 public void testInterpolator() throws Throwable { 441 enterScene(R.layout.scene1); 442 View redSquare = mActivity.findViewById(R.id.redSquare); 443 CaptureAnimatorTransition transition = new CaptureAnimatorTransition(); 444 assertNull(transition.getInterpolator()); 445 AccelerateInterpolator interpolator = new AccelerateInterpolator(); 446 transition.setInterpolator(interpolator); 447 assertSame(interpolator, transition.getInterpolator()); 448 mTransition = transition; 449 resetListener(); 450 startTransition(R.layout.scene4); 451 assertFalse(transition.animators.isEmpty()); 452 Animator animator = transition.animators.get(redSquare); 453 Animator.AnimatorListener listener = transition.listeners.get(redSquare); 454 verify(listener, within(100)).onAnimationStart(any(), eq(false)); 455 assertSame(interpolator, animator.getInterpolator()); 456 endTransition(); 457 } 458 459 @Test 460 public void testName() throws Throwable { 461 assertEquals("android.transition.cts.BaseTransitionTest$TestTransition", 462 mTransition.getName()); 463 } 464 465 @Test 466 public void testPathMotion() throws Throwable { 467 PathMotion pathMotion = new ArcMotion(); 468 mTransition.setPathMotion(pathMotion); 469 assertEquals(pathMotion, mTransition.getPathMotion()); 470 } 471 472 @Test 473 public void testPropagation() throws Throwable { 474 enterScene(R.layout.scene1); 475 CaptureAnimatorTransition transition = new CaptureAnimatorTransition(); 476 mTransition = transition; 477 TransitionPropagation yPropagation = new TransitionPropagation() { 478 private static final String TOP = "top value"; 479 private final String[] PROPERTIES = {TOP}; 480 481 @Override 482 public long getStartDelay(ViewGroup viewGroup, Transition transition, 483 TransitionValues startValues, TransitionValues endValues) { 484 int startTop = startValues == null ? 0 : (Integer) startValues.values.get(TOP); 485 int endTop = endValues == null ? 0 : (Integer) endValues.values.get(TOP); 486 return (startTop == 0) ? endTop : startTop; 487 } 488 489 @Override 490 public void captureValues(TransitionValues transitionValues) { 491 if (transitionValues.view != null) { 492 transitionValues.values.put(TOP, transitionValues.view.getTop()); 493 } 494 } 495 496 @Override 497 public String[] getPropagationProperties() { 498 return PROPERTIES; 499 } 500 }; 501 mTransition.setPropagation(yPropagation); 502 resetListener(); 503 504 View redSquare = mActivity.findViewById(R.id.redSquare); 505 View greenSquare = mActivity.findViewById(R.id.greenSquare); 506 int diffTop = greenSquare.getTop() - redSquare.getTop(); 507 startTransition(R.layout.scene4); 508 Animator redSquareAnimator = transition.animators.get(redSquare); 509 Animator greenSquareAnimator = transition.animators.get(greenSquare); 510 Animator.AnimatorListener listener = transition.listeners.get(redSquare); 511 verify(listener, within(100)).onAnimationStart(any(), eq(false)); 512 assertEquals(0, redSquareAnimator.getStartDelay()); 513 assertEquals(diffTop, greenSquareAnimator.getStartDelay()); 514 endTransition(); 515 } 516 517 @Test 518 public void testSetPropagation() throws Throwable { 519 Transition transition = new ChangeBounds(); 520 assertNull(transition.getPropagation()); 521 TransitionPropagation propagation = new CircularPropagation(); 522 transition.setPropagation(propagation); 523 assertSame(propagation, transition.getPropagation()); 524 } 525 526 @Test 527 public void testStartDelay() throws Throwable { 528 CaptureAnimatorTransition transition = new CaptureAnimatorTransition(); 529 mTransition = transition; 530 resetListener(); 531 enterScene(R.layout.scene1); 532 View redSquare = mActivity.findViewById(R.id.redSquare); 533 534 assertEquals(-1, mTransition.getStartDelay()); 535 mTransition.setStartDelay(200); 536 assertEquals(200, mTransition.getStartDelay()); 537 538 startTransition(R.layout.scene4); 539 540 Animator animator = transition.animators.get(redSquare); 541 assertFalse(animator.isRunning()); 542 Animator.AnimatorListener listener = transition.listeners.get(redSquare); 543 verify(listener, within(250)).onAnimationStart(any(), eq(false)); 544 endTransition(); 545 } 546 547 @Test 548 public void testTransitionValues() throws Throwable { 549 enterScene(R.layout.scene1); 550 CheckTransitionValuesTransition transition = new CheckTransitionValuesTransition(); 551 mTransition = transition; 552 mTransition.setDuration(10); 553 resetListener(); 554 startTransition(R.layout.scene2); 555 assertTrue(transition.onDisappearCalled.await(500, TimeUnit.MILLISECONDS)); 556 assertTrue(transition.onAppearCalled.await(500, TimeUnit.MILLISECONDS)); 557 // The transition has all the asserts in it, so we can just end it now. 558 endTransition(); 559 } 560 561 @Test 562 public void testMatchOrder() throws Throwable { 563 mTransition = new ChangeBounds(); 564 resetListener(); 565 enterScene(R.layout.scene1); 566 startTransition(R.layout.scene8); 567 568 // scene 8 swaps the ids, but not the names. No transition should happen. 569 waitForEnd(0); 570 571 // now change the match order to prefer the id 572 mTransition.setMatchOrder(new int[] {Transition.MATCH_ID, Transition.MATCH_NAME}); 573 574 resetListener(); 575 startTransition(R.layout.scene1); 576 verify(mListener, never()).onTransitionEnd(any()); // it is running as expected 577 waitForEnd(1000); 578 } 579 580 @Test 581 public void testGetTransitionProperties() throws Throwable { 582 enterScene(R.layout.scene1); 583 // Make the transition make changes to properties in getTransitionProperties. 584 TransitionPropertiesTransition transition = new TransitionPropertiesTransition(false); 585 mTransition = transition; 586 resetListener(); 587 startTransition(R.layout.scene2); 588 assertTrue(transition.latch.await(500, TimeUnit.MILLISECONDS)); 589 endTransition(); 590 591 // Now make the transition only make changes to unimportant properties. 592 transition = new TransitionPropertiesTransition(true); 593 mTransition = transition; 594 resetListener(); 595 startTransition(R.layout.scene1); 596 verify(mListener, within(500)).onTransitionEnd(any()); 597 // createAnimator shouldn't have been called. 598 assertEquals(1, transition.latch.getCount()); 599 600 assertNotNull(transition.getTransitionProperties()); 601 assertEquals(1, transition.getTransitionProperties().length); 602 } 603 604 @Test 605 public void testGoWithNullParameter() throws Throwable { 606 final View layout1 = loadLayout(R.layout.scene1); 607 final Scene scene1 = loadScene(layout1); 608 609 final View layout3 = loadLayout(R.layout.scene3); 610 final Scene scene3 = loadScene(layout3); 611 612 enterScene(scene1); 613 614 mActivityRule.runOnUiThread(() -> { 615 // scene1 616 assertSame(layout1, mActivity.findViewById(R.id.holder)); 617 assertNotNull(mActivity.findViewById(R.id.hello)); 618 619 TransitionManager.go(scene3, null); 620 // now at scene3 621 assertSame(layout3, mActivity.findViewById(R.id.holder)); 622 assertNull(mActivity.findViewById(R.id.hello)); 623 624 TransitionManager.go(scene1, null); 625 626 // now at scene1 627 assertSame(layout1, mActivity.findViewById(R.id.holder)); 628 assertNotNull(mActivity.findViewById(R.id.hello)); 629 }); 630 } 631 632 private class NotRequiredTransition extends TestTransition { 633 @Override 634 public boolean isTransitionRequired(TransitionValues startValues, 635 TransitionValues newValues) { 636 return false; 637 } 638 } 639 640 private class CaptureAnimatorTransition extends TestTransition { 641 public HashMap<View, Animator> animators = new HashMap<>(); 642 public HashMap<View, Animator.AnimatorListener> listeners = new HashMap<>(); 643 644 @Override 645 public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, 646 TransitionValues endValues) { 647 return setupAnimator(super.onAppear(sceneRoot, view, startValues, endValues), 648 endValues.view); 649 } 650 651 @Override 652 public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 653 TransitionValues endValues) { 654 return setupAnimator(super.onDisappear(sceneRoot, view, startValues, endValues), 655 startValues.view); 656 } 657 658 private Animator setupAnimator(Animator animator, View view) { 659 animators.put(view, animator); 660 Animator.AnimatorListener listener = mock(Animator.AnimatorListener.class); 661 animator.addListener(listener); 662 listeners.put(view, listener); 663 return animator; 664 } 665 } 666 667 private class CheckTransitionValuesTransition extends TestTransition { 668 public CountDownLatch onAppearCalled = new CountDownLatch(1); 669 public CountDownLatch onDisappearCalled = new CountDownLatch(1); 670 @Override 671 public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, 672 TransitionValues endValues) { 673 onAppearCalled.countDown(); 674 assertNull(getTransitionValues(endValues.view, true)); 675 assertEquals(endValues, getTransitionValues(endValues.view, false)); 676 return super.onAppear(sceneRoot, view, startValues, endValues); 677 } 678 679 @Override 680 public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 681 TransitionValues endValues) { 682 onDisappearCalled.countDown(); 683 assertNull(getTransitionValues(startValues.view, false)); 684 assertEquals(startValues, getTransitionValues(startValues.view, true)); 685 return super.onDisappear(sceneRoot, view, startValues, endValues); 686 } 687 } 688 689 private static class TransitionPropertiesTransition extends Transition { 690 private static final String SIDE_PROP = "prop1"; 691 private static final String IMPORTANT_PROP = "prop2"; 692 private static final String[] PROPERTIES = { 693 IMPORTANT_PROP 694 }; 695 696 private boolean mOnlyUnimportant; 697 public CountDownLatch latch = new CountDownLatch(1); 698 699 public TransitionPropertiesTransition(boolean onlyUnimportant) { 700 mOnlyUnimportant = onlyUnimportant; 701 } 702 703 @Override 704 public String[] getTransitionProperties() { 705 return PROPERTIES; 706 } 707 708 @Override 709 public void captureStartValues(TransitionValues transitionValues) { 710 transitionValues.values.put(SIDE_PROP, 1); 711 transitionValues.values.put(IMPORTANT_PROP, 1); 712 } 713 714 @Override 715 public void captureEndValues(TransitionValues transitionValues) { 716 transitionValues.values.put(SIDE_PROP, 2); 717 int val = mOnlyUnimportant ? 1 : 2; 718 transitionValues.values.put(IMPORTANT_PROP, val); 719 } 720 721 @Override 722 public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, 723 TransitionValues endValues) { 724 if (startValues != null && endValues != null) { 725 latch.countDown(); 726 } 727 728 return null; 729 } 730 } 731 732 private static class DurationListener extends TransitionListenerAdapter { 733 734 private long mUptimeMillisStart = -1; 735 private long mDuration = -1; 736 737 @Override 738 public void onTransitionStart(Transition transition) { 739 mUptimeMillisStart = SystemClock.uptimeMillis(); 740 } 741 742 @Override 743 public void onTransitionEnd(Transition transition) { 744 mDuration = SystemClock.uptimeMillis() - mUptimeMillisStart; 745 } 746 747 public long getDuration() { 748 if (mDuration < 0) { 749 fail("Requested duration measurement of an incomplete transition."); 750 } 751 return mDuration; 752 } 753 } 754 } 755