1 /* 2 * Copyright (C) 2012 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.animation.cts; 17 18 import static com.android.compatibility.common.util.CtsMockitoUtils.within; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.mockito.Mockito.atLeast; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.timeout; 27 import static org.mockito.Mockito.times; 28 import static org.mockito.Mockito.verify; 29 30 import android.animation.Animator; 31 import android.animation.Animator.AnimatorListener; 32 import android.animation.AnimatorListenerAdapter; 33 import android.animation.ObjectAnimator; 34 import android.animation.PropertyValuesHolder; 35 import android.animation.TypeEvaluator; 36 import android.animation.ValueAnimator; 37 import android.graphics.Color; 38 import android.graphics.PointF; 39 import android.os.SystemClock; 40 import android.support.test.InstrumentationRegistry; 41 import android.support.test.annotation.UiThreadTest; 42 import android.support.test.filters.LargeTest; 43 import android.support.test.rule.ActivityTestRule; 44 import android.support.test.runner.AndroidJUnit4; 45 import android.view.animation.AccelerateInterpolator; 46 import android.view.animation.LinearInterpolator; 47 48 import org.junit.AfterClass; 49 import org.junit.Before; 50 import org.junit.BeforeClass; 51 import org.junit.Rule; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 55 import java.util.concurrent.CountDownLatch; 56 import java.util.concurrent.TimeUnit; 57 58 @LargeTest 59 @RunWith(AndroidJUnit4.class) 60 public class ValueAnimatorTest { 61 private static final float EPSILON = 0.0001f; 62 private static float sPreviousAnimatorScale = 1.0f; 63 64 private AnimationActivity mActivity; 65 private ValueAnimator mValueAnimator; 66 private final long mDuration = 2000; 67 68 @Rule 69 public ActivityTestRule<AnimationActivity> mActivityRule = 70 new ActivityTestRule<>(AnimationActivity.class); 71 72 @Before setup()73 public void setup() { 74 InstrumentationRegistry.getInstrumentation().setInTouchMode(false); 75 mActivity = mActivityRule.getActivity(); 76 mValueAnimator = mActivity.createAnimatorWithDuration(mDuration); 77 } 78 79 @BeforeClass beforeClass()80 public static void beforeClass() { 81 sPreviousAnimatorScale = ValueAnimator.getDurationScale(); 82 ValueAnimator.setDurationScale(1.0f); 83 } 84 85 @AfterClass afterClass()86 public static void afterClass() { 87 ValueAnimator.setDurationScale(sPreviousAnimatorScale); 88 } 89 90 @Test testDuration()91 public void testDuration() throws Throwable { 92 ValueAnimator valueAnimatorLocal = mActivity.createAnimatorWithDuration(mDuration); 93 startAnimation(valueAnimatorLocal); 94 assertEquals(mDuration, valueAnimatorLocal.getDuration()); 95 } 96 97 @Test testIsRunning()98 public void testIsRunning() throws Throwable { 99 assertFalse(mValueAnimator.isRunning()); 100 startAnimation(mValueAnimator); 101 ValueAnimator valueAnimatorReturned = mActivity.view.bounceYAnimator; 102 assertTrue(valueAnimatorReturned.isRunning()); 103 } 104 105 @Test testIsStarted()106 public void testIsStarted() throws Throwable { 107 assertFalse(mValueAnimator.isRunning()); 108 assertFalse(mValueAnimator.isStarted()); 109 long startDelay = 10000; 110 mValueAnimator.setStartDelay(startDelay); 111 startAnimation(mValueAnimator); 112 assertFalse(mValueAnimator.isRunning()); 113 assertTrue(mValueAnimator.isStarted()); 114 } 115 116 @Test testRepeatMode()117 public void testRepeatMode() throws Throwable { 118 ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatMode( 119 ValueAnimator.RESTART); 120 startAnimation(mValueAnimator); 121 assertEquals(ValueAnimator.RESTART, mValueAnimator.getRepeatMode()); 122 } 123 124 @Test testRepeatCount()125 public void testRepeatCount() throws Throwable { 126 int repeatCount = 2; 127 ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatCount(repeatCount); 128 startAnimation(mValueAnimator); 129 assertEquals(repeatCount, mValueAnimator.getRepeatCount()); 130 } 131 132 @Test testStartDelay()133 public void testStartDelay() { 134 long startDelay = 1000; 135 mValueAnimator.setStartDelay(startDelay); 136 assertEquals(startDelay, mValueAnimator.getStartDelay()); 137 } 138 139 /** 140 * Verify that an animator with start delay will have its listener's onAnimationStart(...) 141 * and onAnimationEnd(...) called at the right time. 142 */ 143 @Test testListenerCallbackWithStartDelay()144 public void testListenerCallbackWithStartDelay() throws Throwable { 145 final ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); 146 anim.setStartDelay(300); 147 anim.setDuration(300); 148 AnimatorListener listener = mock(AnimatorListenerAdapter.class); 149 anim.addListener(listener); 150 mActivityRule.runOnUiThread(() -> { 151 anim.start(); 152 }); 153 154 verify(listener, timeout(450).times(1)).onAnimationStart(anim, false); 155 verify(listener, timeout(450).times(1)).onAnimationEnd(anim, false); 156 } 157 158 @Test testGetCurrentPlayTime()159 public void testGetCurrentPlayTime() throws Throwable { 160 startAnimation(mValueAnimator); 161 SystemClock.sleep(100); 162 long currentPlayTime = mValueAnimator.getCurrentPlayTime(); 163 assertTrue(currentPlayTime > 0); 164 } 165 166 @Test testSetCurrentPlayTime()167 public void testSetCurrentPlayTime() throws Throwable { 168 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 169 final ValueAnimator delayedAnim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 170 delayedAnim.setStartDelay(mDuration); 171 final long proposedCurrentPlayTime = mDuration / 2; 172 mActivityRule.runOnUiThread(() -> { 173 anim.setCurrentPlayTime(mDuration / 2); 174 long currentPlayTime = anim.getCurrentPlayTime(); 175 float currentFraction = anim.getAnimatedFraction(); 176 float currentValue = (Float) anim.getAnimatedValue(); 177 assertEquals(proposedCurrentPlayTime, currentPlayTime); 178 assertEquals(.5f, currentFraction, EPSILON); 179 assertEquals(50, currentValue, EPSILON); 180 181 delayedAnim.setCurrentPlayTime(mDuration / 2); 182 currentPlayTime = delayedAnim.getCurrentPlayTime(); 183 currentFraction = delayedAnim.getAnimatedFraction(); 184 currentValue = (Float) delayedAnim.getAnimatedValue(); 185 assertEquals(proposedCurrentPlayTime, currentPlayTime); 186 assertEquals(.5f, currentFraction, EPSILON); 187 assertEquals(50, currentValue, EPSILON); 188 }); 189 // Now make sure that it's still true a little later, to test that we're 190 // getting a result based on the seek time, not the wall clock time 191 SystemClock.sleep(100); 192 long currentPlayTime = anim.getCurrentPlayTime(); 193 float currentFraction = anim.getAnimatedFraction(); 194 float currentValue = (Float) anim.getAnimatedValue(); 195 assertEquals(proposedCurrentPlayTime, currentPlayTime); 196 assertEquals(.5f, currentFraction, EPSILON); 197 assertEquals(50, currentValue, EPSILON); 198 199 currentPlayTime = delayedAnim.getCurrentPlayTime(); 200 currentFraction = delayedAnim.getAnimatedFraction(); 201 currentValue = (Float) delayedAnim.getAnimatedValue(); 202 assertEquals(proposedCurrentPlayTime, currentPlayTime); 203 assertEquals(.5f, currentFraction, EPSILON); 204 assertEquals(50, currentValue, EPSILON); 205 206 // Finally, start() the delayed animation and check that the play time was 207 // not affected by playing during the delay 208 mActivityRule.runOnUiThread(() -> { 209 delayedAnim.start(); 210 assertEquals(proposedCurrentPlayTime, delayedAnim.getCurrentPlayTime()); 211 assertEquals(.5f, delayedAnim.getAnimatedFraction(), EPSILON); 212 assertEquals(50, (float) delayedAnim.getAnimatedValue(), EPSILON); 213 }); 214 215 SystemClock.sleep(100); 216 currentPlayTime = delayedAnim.getCurrentPlayTime(); 217 currentFraction = delayedAnim.getAnimatedFraction(); 218 currentValue = (Float) delayedAnim.getAnimatedValue(); 219 assertTrue(currentPlayTime > proposedCurrentPlayTime); 220 assertTrue(currentFraction > 0.5f); 221 assertTrue(currentValue > 50); 222 223 mActivityRule.runOnUiThread(delayedAnim::cancel); 224 } 225 226 @Test testPauseListener()227 public void testPauseListener() throws Throwable { 228 // Adds two pause listeners to the animator, and remove one after the animator is paused. 229 Animator.AnimatorPauseListener l1 = mock(Animator.AnimatorPauseListener.class); 230 Animator.AnimatorPauseListener l2 = mock(Animator.AnimatorPauseListener.class); 231 ValueAnimator a1 = ValueAnimator.ofFloat(0, 1f); 232 a1.addPauseListener(l1); 233 a1.addPauseListener(l2); 234 mActivityRule.runOnUiThread(() -> { 235 a1.start(); 236 a1.pause(); 237 verify(l1, times(1)).onAnimationPause(a1); 238 verify(l2, times(1)).onAnimationPause(a1); 239 a1.removePauseListener(l2); 240 a1.resume(); 241 }); 242 243 // Check that the pause listener that is removed doesn't have resume called. 244 verify(l1, times(1)).onAnimationResume(a1); 245 verify(l2, times(0)).onAnimationResume(a1); 246 } 247 248 @Test testSetCurrentPlayTimeAfterStart()249 public void testSetCurrentPlayTimeAfterStart() throws Throwable { 250 // This test sets current play time right after start() is called on a non-delayed animation 251 final long duration = 100; 252 final float seekFraction = 0.2f; 253 final CountDownLatch frameUpdateLatch = new CountDownLatch(1); 254 255 final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener(); 256 final ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(duration); 257 anim.setInterpolator(null); 258 final Animator.AnimatorListener listener = mock(Animator.AnimatorListener.class); 259 anim.addListener(listener); 260 anim.addListener(myListener); 261 mActivityRule.runOnUiThread(() -> { 262 anim.start(); 263 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 264 float fractionOnFirstFrame = -1f; 265 266 @Override 267 public void onAnimationUpdate(ValueAnimator animation) { 268 if (fractionOnFirstFrame < 0) { 269 // First frame: 270 fractionOnFirstFrame = animation.getAnimatedFraction(); 271 assertEquals(seekFraction, fractionOnFirstFrame, EPSILON); 272 frameUpdateLatch.countDown(); 273 } else { 274 assertTrue(animation.getAnimatedFraction() >= fractionOnFirstFrame); 275 } 276 } 277 }); 278 long currentPlayTime = (long) (seekFraction * (float) duration); 279 anim.setCurrentPlayTime(currentPlayTime); 280 }); 281 assertTrue(frameUpdateLatch.await(100, TimeUnit.MILLISECONDS)); 282 verify(listener, within(200)).onAnimationEnd(anim, false); 283 // Also make sure the onAnimationEnd(anim) is called. 284 assertTrue(myListener.mEndIsCalled); 285 } 286 287 @Test testSetCurrentFraction()288 public void testSetCurrentFraction() throws Throwable { 289 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 290 final long proposedCurrentPlayTime = mDuration / 2; 291 mActivityRule.runOnUiThread(() -> { 292 anim.setCurrentFraction(.5f); 293 long currentPlayTime = anim.getCurrentPlayTime(); 294 float currentFraction = anim.getAnimatedFraction(); 295 float currentValue = (Float) anim.getAnimatedValue(); 296 assertEquals(proposedCurrentPlayTime, currentPlayTime); 297 assertEquals(.5f, currentFraction, EPSILON); 298 assertEquals(50, currentValue, EPSILON); 299 }); 300 // Now make sure that it's still true a little later, to test that we're 301 // getting a result based on the seek time, not the wall clock time 302 SystemClock.sleep(100); 303 long currentPlayTime = anim.getCurrentPlayTime(); 304 float currentFraction = anim.getAnimatedFraction(); 305 float currentValue = (Float) anim.getAnimatedValue(); 306 assertEquals(proposedCurrentPlayTime, currentPlayTime); 307 assertEquals(.5f, currentFraction, EPSILON); 308 assertEquals(50, currentValue, EPSILON); 309 } 310 311 @UiThreadTest 312 @Test testReverseRightAfterStart()313 public void testReverseRightAfterStart() { 314 // Reverse() right after start() should trigger immediate end() at fraction 0. 315 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 316 anim.start(); 317 assertTrue(anim.isStarted()); 318 anim.reverse(); 319 assertFalse(anim.isStarted()); 320 assertEquals(0f, anim.getAnimatedFraction(), 0.0f); 321 } 322 323 @Test testGetFrameDelay()324 public void testGetFrameDelay() throws Throwable { 325 final long frameDelay = 10; 326 mActivityRule.runOnUiThread(() -> mValueAnimator.setFrameDelay(frameDelay)); 327 startAnimation(mValueAnimator); 328 SystemClock.sleep(100); 329 mActivityRule.runOnUiThread(() -> { 330 long actualFrameDelay = mValueAnimator.getFrameDelay(); 331 assertEquals(frameDelay, actualFrameDelay); 332 }); 333 } 334 335 @Test testUpdateListeners()336 public void testUpdateListeners() throws Throwable { 337 final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener(); 338 ValueAnimator.AnimatorUpdateListener l1 = mock(ValueAnimator.AnimatorUpdateListener.class); 339 ValueAnimator.AnimatorUpdateListener l2 = mock(ValueAnimator.AnimatorUpdateListener.class); 340 ValueAnimator.AnimatorUpdateListener l3 = mock(ValueAnimator.AnimatorUpdateListener.class); 341 ValueAnimator.AnimatorUpdateListener l4 = mock(ValueAnimator.AnimatorUpdateListener.class); 342 343 AnimatorListenerAdapter listener = mock(AnimatorListenerAdapter.class); 344 345 ValueAnimator a1 = ValueAnimator.ofFloat(0, 1f); 346 a1.setDuration(50); 347 a1.addUpdateListener(l1); 348 a1.addUpdateListener(l2); 349 a1.removeAllUpdateListeners(); 350 351 a1.addUpdateListener(l3); 352 a1.addUpdateListener(l4); 353 a1.removeUpdateListener(l3); 354 355 a1.addListener(listener); 356 a1.addListener(myListener); 357 358 mActivityRule.runOnUiThread(() -> { 359 a1.start(); 360 }); 361 362 // Wait for the anim to finish. 363 verify(listener, within(200)).onAnimationEnd(a1, false); 364 // Also make sure the onAnimationEnd(anim) is called. 365 assertTrue(myListener.mEndIsCalled); 366 367 verify(l1, times(0)).onAnimationUpdate(a1); 368 verify(l2, times(0)).onAnimationUpdate(a1); 369 verify(l3, times(0)).onAnimationUpdate(a1); 370 verify(l4, atLeast(1)).onAnimationUpdate(a1); 371 } 372 373 @Test testValuesSetterAndGetter()374 public void testValuesSetterAndGetter() throws Throwable { 375 376 final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener(); 377 ValueAnimator a2 = ValueAnimator.ofPropertyValuesHolder(); 378 PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f); 379 PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 2f); 380 a2.setValues(p1, p2); 381 PropertyValuesHolder[] holders = a2.getValues(); 382 assertEquals(2, holders.length); 383 384 // Use the PropertyValueHolders returned from the getter to initialize the animator, in 385 // order to test the getter. 386 ValueAnimator a1 = ValueAnimator.ofPropertyValuesHolder(holders); 387 a1.setDuration(50); 388 a1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 389 @Override 390 public void onAnimationUpdate(ValueAnimator animation) { 391 float scaleX = (Float) animation.getAnimatedValue("scaleX"); 392 float scaleY = (Float) animation.getAnimatedValue("scaleY"); 393 assertTrue(scaleX >= 0f && scaleX <= 1f); 394 assertTrue(scaleY >= 1f && scaleY <= 2f); 395 } 396 }); 397 AnimatorListenerAdapter l1 = mock(AnimatorListenerAdapter.class); 398 a1.addListener(l1); 399 a1.addListener(myListener); 400 401 mActivityRule.runOnUiThread(() -> { 402 a1.start(); 403 }); 404 405 verify(l1, within(200)).onAnimationEnd(a1, false); 406 // Also make sure the onAnimationEnd(anim) is called. 407 assertTrue(myListener.mEndIsCalled); 408 } 409 410 @Test testSetObjectValues()411 public void testSetObjectValues() throws Throwable { 412 TypeEvaluator<PointF> eval = new TypeEvaluator<PointF>() { 413 PointF tmpValue = new PointF(); 414 @Override 415 public PointF evaluate(float fraction, PointF startValue, PointF endValue) { 416 tmpValue.x = fraction * startValue.x + (1f - fraction) * endValue.x; 417 tmpValue.y = fraction * startValue.y + (1f - fraction) * endValue.y; 418 return tmpValue; 419 } 420 }; 421 422 final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener(); 423 ValueAnimator a1 = new ValueAnimator(); 424 a1.setDuration(50); 425 a1.setObjectValues(new PointF(0, 0), new PointF(1, 1)); 426 a1.setEvaluator(eval); 427 a1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 428 @Override 429 public void onAnimationUpdate(ValueAnimator animation) { 430 PointF point = (PointF) animation.getAnimatedValue(); 431 assertTrue(point.x >= 0f && point.x <= 1f); 432 assertTrue(point.y >= 0f && point.y <= 1f); 433 } 434 }); 435 AnimatorListenerAdapter l1 = mock(AnimatorListenerAdapter.class); 436 a1.addListener(l1); 437 a1.addListener(myListener); 438 mActivityRule.runOnUiThread(() -> { 439 a1.start(); 440 }); 441 442 verify(l1, within(200)).onAnimationEnd(a1, false); 443 // Also make sure the onAnimationEnd(anim) is called. 444 assertTrue(myListener.mEndIsCalled); 445 } 446 447 @Test testSetInterpolator()448 public void testSetInterpolator() throws Throwable { 449 AccelerateInterpolator interpolator = new AccelerateInterpolator(); 450 ValueAnimator mValueAnimator = mActivity.createAnimatorWithInterpolator(interpolator); 451 startAnimation(mValueAnimator); 452 assertTrue(interpolator.equals(mValueAnimator.getInterpolator())); 453 } 454 455 @Test testCancel()456 public void testCancel() throws Throwable { 457 startAnimation(mValueAnimator); 458 SystemClock.sleep(100); 459 cancelAnimation(mValueAnimator); 460 assertFalse(mValueAnimator.isRunning()); 461 } 462 463 @Test testEnd()464 public void testEnd() throws Throwable { 465 Object object = mActivity.view.newBall; 466 String property = "y"; 467 float startY = mActivity.mStartY; 468 float endY = mActivity.mStartY + mActivity.mDeltaY; 469 ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY); 470 objAnimator.setDuration(mDuration); 471 objAnimator.setRepeatCount(ValueAnimator.INFINITE); 472 objAnimator.setInterpolator(new AccelerateInterpolator()); 473 objAnimator.setRepeatMode(ValueAnimator.REVERSE); 474 startAnimation(objAnimator); 475 SystemClock.sleep(100); 476 endAnimation(objAnimator); 477 float y = mActivity.view.newBall.getY(); 478 assertEquals(y, endY, 0.0f); 479 } 480 481 @Test testGetAnimatedFraction()482 public void testGetAnimatedFraction() throws Throwable { 483 ValueAnimator objAnimator = getAnimator(); 484 startAnimation(objAnimator); 485 assertNotNull(objAnimator); 486 float[] fractions = getValue(objAnimator, 10, "getAnimatedFraction()", 200l, null); 487 for(int j = 0; j < 9; j++){ 488 assertTrue(fractions[j] >= 0.0); 489 assertTrue(fractions[j] <= 1.0); 490 assertTrue(errorMessage(fractions), fractions[j + 1] >= fractions[j]); 491 } 492 } 493 494 @Test testGetAnimatedValue()495 public void testGetAnimatedValue() throws Throwable { 496 ValueAnimator objAnimator = getAnimator(); 497 startAnimation(objAnimator); 498 assertNotNull(objAnimator); 499 float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue()", 200l, null); 500 501 for(int j = 0; j < 9; j++){ 502 assertTrue(errorMessage(animatedValues), animatedValues[j + 1] >= animatedValues[j]); 503 } 504 } 505 506 @Test testGetAnimatedValue_PropertyName()507 public void testGetAnimatedValue_PropertyName() throws Throwable { 508 String property = "y"; 509 510 ValueAnimator objAnimator = getAnimator(); 511 startAnimation(objAnimator); 512 assertNotNull(objAnimator); 513 float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue(property)", 200l, 514 property); 515 for(int j = 0; j < 9; j++){ 516 assertTrue(errorMessage(animatedValues), animatedValues[j + 1] >= animatedValues[j]); 517 } 518 } 519 520 @Test testOfFloat()521 public void testOfFloat() throws Throwable { 522 float start = 0.0f; 523 float end = 1.0f; 524 float[] values = {start, end}; 525 final ValueAnimator valueAnimatorLocal = ValueAnimator.ofFloat(values); 526 valueAnimatorLocal.setDuration(mDuration); 527 valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE); 528 valueAnimatorLocal.setInterpolator(new AccelerateInterpolator()); 529 valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART); 530 531 mActivityRule.runOnUiThread(valueAnimatorLocal::start); 532 SystemClock.sleep(100); 533 boolean isRunning = valueAnimatorLocal.isRunning(); 534 assertTrue(isRunning); 535 536 Float animatedValue = (Float) valueAnimatorLocal.getAnimatedValue(); 537 assertTrue(animatedValue >= start); 538 assertTrue(animatedValue <= end); 539 } 540 541 @Test testOfInt()542 public void testOfInt() throws Throwable { 543 int start = 0; 544 int end = 10; 545 int[] values = {start, end}; 546 final ValueAnimator valueAnimatorLocal = ValueAnimator.ofInt(values); 547 valueAnimatorLocal.setDuration(mDuration); 548 valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE); 549 valueAnimatorLocal.setInterpolator(new AccelerateInterpolator()); 550 valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART); 551 552 mActivityRule.runOnUiThread(valueAnimatorLocal::start); 553 SystemClock.sleep(100); 554 boolean isRunning = valueAnimatorLocal.isRunning(); 555 assertTrue(isRunning); 556 557 Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue(); 558 assertTrue(animatedValue >= start); 559 assertTrue(animatedValue <= end); 560 } 561 562 @Test testOfArgb()563 public void testOfArgb() throws Throwable { 564 int start = 0xffff0000; 565 int end = 0xff0000ff; 566 int[] values = {start, end}; 567 int startRed = Color.red(start); 568 int startBlue = Color.blue(start); 569 int endRed = Color.red(end); 570 int endBlue = Color.blue(end); 571 final ValueAnimator valueAnimatorLocal = ValueAnimator.ofArgb(values); 572 valueAnimatorLocal.setDuration(mDuration); 573 574 final CountDownLatch latch = new CountDownLatch(1); 575 valueAnimatorLocal.addUpdateListener((ValueAnimator animation) -> { 576 if (animation.getAnimatedFraction() > .05f) { 577 latch.countDown(); 578 } 579 }); 580 581 mActivityRule.runOnUiThread(valueAnimatorLocal::start); 582 boolean isRunning = valueAnimatorLocal.isRunning(); 583 assertTrue(isRunning); 584 585 assertTrue(latch.await(500, TimeUnit.MILLISECONDS)); 586 587 Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue(); 588 int alpha = Color.alpha(animatedValue); 589 int red = Color.red(animatedValue); 590 int green = Color.green(animatedValue); 591 int blue = Color.blue(animatedValue); 592 assertTrue(red < startRed); 593 assertTrue(red > endRed); 594 assertTrue(blue > startBlue); 595 assertTrue(blue < endBlue); 596 assertEquals(255, alpha); 597 assertEquals(0, green); 598 599 mActivityRule.runOnUiThread(valueAnimatorLocal::cancel); 600 } 601 602 @Test 603 public void testNoDelayOnSeekAnimation() throws Throwable { 604 ValueAnimator animator = ValueAnimator.ofFloat(0, 1); 605 animator.setInterpolator(new LinearInterpolator()); 606 animator.setStartDelay(1000); 607 animator.setDuration(300); 608 animator.setCurrentPlayTime(150); 609 final Animator.AnimatorListener watcher = mock(Animator.AnimatorListener.class); 610 animator.addListener(watcher); 611 mActivityRule.runOnUiThread(animator::start); 612 verify(watcher, times(1)).onAnimationStart(animator, false); 613 assertTrue(((Float)animator.getAnimatedValue()) >= 0.5f); 614 assertTrue(animator.getAnimatedFraction() >= 0.5f); 615 mActivityRule.runOnUiThread(animator::cancel); 616 } 617 618 @Test testNotifiesAfterEnd()619 public void testNotifiesAfterEnd() throws Throwable { 620 final ValueAnimator animator = ValueAnimator.ofFloat(0, 1); 621 animator.addListener(new AnimatorListenerAdapter() { 622 @Override 623 public void onAnimationStart(Animator animation) { 624 assertTrue(animation.isStarted()); 625 assertTrue(animation.isRunning()); 626 } 627 628 @Override 629 public void onAnimationEnd(Animator animation) { 630 assertFalse(animation.isRunning()); 631 assertFalse(animation.isStarted()); 632 super.onAnimationEnd(animation); 633 } 634 }); 635 mActivityRule.runOnUiThread(() -> { 636 animator.start(); 637 animator.end(); 638 }); 639 } 640 641 @Test testAnimatorsEnabled()642 public void testAnimatorsEnabled() throws Throwable { 643 float currentDurationScale = ValueAnimator.getDurationScale(); 644 try { 645 testAnimatorsEnabledImpl(true); 646 testAnimatorsEnabledImpl(false); 647 } finally { 648 // restore scale value to avoid messing up future tests 649 ValueAnimator.setDurationScale(currentDurationScale); 650 } 651 } 652 testAnimatorsEnabledImpl(boolean enabled)653 private void testAnimatorsEnabledImpl(boolean enabled) throws Throwable { 654 final CountDownLatch endLatch = new CountDownLatch(1); 655 final ValueAnimator animator = ValueAnimator.ofFloat(0, 1); 656 animator.setDuration(1000); 657 animator.addListener(new AnimatorListenerAdapter() { 658 @Override 659 public void onAnimationEnd(Animator animation) { 660 endLatch.countDown(); 661 } 662 }); 663 mActivityRule.runOnUiThread(() -> { 664 animator.start(); 665 }); 666 667 float durationScale = enabled ? 1 : 0; 668 ValueAnimator.setDurationScale(durationScale); 669 670 if (enabled) { 671 assertTrue("Animators not enabled with duration scale 1", 672 ValueAnimator.areAnimatorsEnabled()); 673 assertFalse("Animator ended too early when animators enabled = ", 674 endLatch.await(50, TimeUnit.MILLISECONDS)); 675 } else { 676 assertFalse("Animators enabled with duration scale 0", 677 ValueAnimator.areAnimatorsEnabled()); 678 assertTrue("Animator did not end when animators enabled = ", 679 endLatch.await(50, TimeUnit.MILLISECONDS)); 680 } 681 mActivityRule.runOnUiThread(() -> { 682 animator.end(); 683 }); 684 } 685 getAnimator()686 private ValueAnimator getAnimator() { 687 Object object = mActivity.view.newBall; 688 String property = "y"; 689 float startY = mActivity.mStartY; 690 float endY = mActivity.mStartY + mActivity.mDeltaY; 691 ValueAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY); 692 objAnimator.setDuration(mDuration); 693 objAnimator.setRepeatCount(ValueAnimator.INFINITE); 694 objAnimator.setInterpolator(new AccelerateInterpolator()); 695 objAnimator.setRepeatMode(ValueAnimator.REVERSE); 696 return objAnimator; 697 } 698 getValue(ValueAnimator animator, int n, String methodName, long sleepTime, String property)699 private float[] getValue(ValueAnimator animator, int n, String methodName, 700 long sleepTime, String property) throws InterruptedException { 701 float[] values = new float[n]; 702 for(int i = 0; i < n; i++){ 703 SystemClock.sleep(sleepTime); 704 float value = 0.0f; 705 if(methodName.equals("getAnimatedFraction()")) { 706 value = animator.getAnimatedFraction(); 707 }else if(methodName.equals("getAnimatedValue()")) { 708 value = ((Float)animator.getAnimatedValue()).floatValue(); 709 }else if(methodName.equals("getAnimatedValue(property)")) { 710 value = ((Float)animator.getAnimatedValue(property)).floatValue(); 711 } 712 values[i] = value; 713 } 714 return values; 715 } 716 startAnimation(final ValueAnimator animator)717 private void startAnimation(final ValueAnimator animator) throws Throwable { 718 mActivityRule.runOnUiThread(() -> mActivity.startAnimation(animator)); 719 } 720 endAnimation(final ValueAnimator animator)721 private void endAnimation(final ValueAnimator animator) throws Throwable { 722 mActivityRule.runOnUiThread(animator::end); 723 } 724 cancelAnimation(final ValueAnimator animator)725 private void cancelAnimation(final ValueAnimator animator) throws Throwable { 726 mActivityRule.runOnUiThread(animator::cancel); 727 } 728 errorMessage(float[] values)729 private String errorMessage(float[] values) { 730 StringBuilder message = new StringBuilder(); 731 for (int i = 0; i < values.length; i++) { 732 message.append(values[i]).append(" "); 733 } 734 return message.toString(); 735 } 736 } 737