1/* 2 * Copyright (C) 2008 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 17package android.view.animation.cts; 18 19import com.android.cts.stub.R; 20 21 22import android.app.ListActivity; 23import android.content.Context; 24import android.content.res.XmlResourceParser; 25import android.test.ActivityInstrumentationTestCase2; 26import android.util.AttributeSet; 27import android.util.Xml; 28import android.view.View; 29import android.view.ViewGroup.LayoutParams; 30import android.view.animation.AccelerateInterpolator; 31import android.view.animation.Animation; 32import android.view.animation.AnimationUtils; 33import android.view.animation.DecelerateInterpolator; 34import android.view.animation.Interpolator; 35import android.view.animation.LayoutAnimationController; 36import android.view.animation.ScaleAnimation; 37import android.view.animation.Transformation; 38import android.view.animation.LayoutAnimationController.AnimationParameters; 39import android.widget.AbsListView; 40import android.widget.ListView; 41 42public class LayoutAnimationControllerTest 43 extends ActivityInstrumentationTestCase2<LayoutAnimStubActivity> { 44 45 private ListActivity mActivity; 46 private Animation mDefaultAnimation; 47 private ListView mListView; 48 private LayoutAnimationController mController; 49 /** Duration defined in layout_anim_controller_animation.xml is 1000 */ 50 private static final int DURATION = 1000; 51 private static final float DELTA = 0.1f; 52 private static final int INDEX_OF_CHILD1 = 0; 53 private static final int INDEX_OF_CHILD2 = 1; 54 private static final int INDEX_OF_CHILD3 = 2; 55 /** Default delay of LayoutAnimationController */ 56 private static final float DEFAULT_DELAY = 0.5f; 57 /** Default max duration of these three children */ 58 private static final long DEFAULT_MAX_DURATION = 2000; 59 60 public LayoutAnimationControllerTest() { 61 super("com.android.cts.stub", LayoutAnimStubActivity.class); 62 } 63 64 @Override 65 protected void setUp() throws Exception { 66 super.setUp(); 67 mActivity = getActivity(); 68 mListView = mActivity.getListView(); 69 mDefaultAnimation = AnimationUtils.loadAnimation(mActivity, 70 R.anim.layout_anim_controller_animation); 71 mController = new LayoutAnimationController(mDefaultAnimation, DEFAULT_DELAY); 72 } 73 74 public void testAccessOrder() throws InterruptedException { 75 76 mController.setOrder(LayoutAnimationController.ORDER_NORMAL); 77 assertEquals(LayoutAnimationController.ORDER_NORMAL, mController.getOrder()); 78 79 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 80 DEFAULT_MAX_DURATION); 81 82 Animation childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 83 Animation childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 84 Animation childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 85 86 // Test normal order 87 long startTime = childAnimation1.getStartTime(); 88 assertEquals(0, childAnimation1.getStartOffset()); 89 assertEquals(500, childAnimation2.getStartOffset()); 90 assertEquals(1000, childAnimation3.getStartOffset()); 91 92 Transformation transformation1 = new Transformation(); 93 Transformation transformation2 = new Transformation(); 94 Transformation transformation3 = new Transformation(); 95 96 // child1 has started animation, child2 and child3 haven't started 97 childAnimation1.getTransformation(startTime + 500, transformation1); 98 childAnimation2.getTransformation(startTime + 500, transformation2); 99 childAnimation3.getTransformation(startTime + 500, transformation3); 100 assertIsRunningAnimation(transformation1.getAlpha()); 101 assertEquals(0.0f, transformation2.getAlpha(), DELTA); 102 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 103 104 // child2 has started animation, child1 has finished and child3 hasn't started 105 childAnimation1.getTransformation(startTime + 1000, transformation1); 106 childAnimation2.getTransformation(startTime + 1000, transformation2); 107 childAnimation3.getTransformation(startTime + 1000, transformation3); 108 assertEquals(1.0f, transformation1.getAlpha(), DELTA); 109 assertIsRunningAnimation(transformation2.getAlpha()); 110 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 111 112 // child3 has started animation, child1, child2 have finished 113 childAnimation1.getTransformation(startTime + 1500, transformation1); 114 childAnimation2.getTransformation(startTime + 1500, transformation2); 115 childAnimation3.getTransformation(startTime + 1500, transformation3); 116 assertEquals(1.0f, transformation1.getAlpha(), DELTA); 117 assertEquals(1.0f, transformation2.getAlpha(), DELTA); 118 assertIsRunningAnimation(transformation3.getAlpha()); 119 120 // Test reverse order 121 mController.setOrder(LayoutAnimationController.ORDER_REVERSE); 122 assertEquals(LayoutAnimationController.ORDER_REVERSE, mController.getOrder()); 123 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 124 DEFAULT_MAX_DURATION); 125 126 transformation1 = new Transformation(); 127 transformation2 = new Transformation(); 128 transformation3 = new Transformation(); 129 childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 130 childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 131 childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 132 startTime = childAnimation1.getStartTime(); 133 assertEquals(1000, childAnimation1.getStartOffset()); 134 assertEquals(500, childAnimation2.getStartOffset()); 135 assertEquals(0, childAnimation3.getStartOffset()); 136 137 // child3 has started animation, child1 and child2 haven't started 138 childAnimation1.getTransformation(startTime + 500, transformation1); 139 childAnimation2.getTransformation(startTime + 500, transformation2); 140 childAnimation3.getTransformation(startTime + 500, transformation3); 141 assertEquals(0.0f, transformation1.getAlpha(), DELTA); 142 assertEquals(0.0f, transformation2.getAlpha(), DELTA); 143 assertIsRunningAnimation(transformation3.getAlpha()); 144 145 // child2 has started animation, child3 has finished and child1 hasn't started 146 childAnimation1.getTransformation(startTime + 1000, transformation1); 147 childAnimation2.getTransformation(startTime + 1000, transformation2); 148 childAnimation3.getTransformation(startTime + 1000, transformation3); 149 assertEquals(0.0f, transformation1.getAlpha(), DELTA); 150 assertIsRunningAnimation(transformation2.getAlpha()); 151 assertEquals(1.0f, transformation3.getAlpha(), DELTA); 152 153 // child1 has started animation, child2 and child3 has finished 154 childAnimation1.getTransformation(startTime + 1500, transformation1); 155 childAnimation2.getTransformation(startTime + 1500, transformation2); 156 childAnimation3.getTransformation(startTime + 1500, transformation3); 157 assertIsRunningAnimation(transformation1.getAlpha()); 158 assertEquals(1.0f, transformation2.getAlpha(), DELTA); 159 assertEquals(1.0f, transformation3.getAlpha(), DELTA); 160 } 161 162 public void testAccessDelay() throws InterruptedException { 163 mController.setOrder(LayoutAnimationController.ORDER_NORMAL); 164 float delay = 1.5f; 165 mController.setDelay(delay); 166 assertEquals(delay, mController.getDelay()); 167 long maxDuration = (long) (delay * INDEX_OF_CHILD3 * DURATION + DURATION); 168 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 169 maxDuration); 170 171 Animation childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 172 Animation childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 173 Animation childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 174 175 long startTime = childAnimation1.getStartTime(); 176 long offsetTime1 = childAnimation1.getStartOffset(); 177 long offsetTime2 = childAnimation2.getStartOffset(); 178 long offsetTime3 = childAnimation3.getStartOffset(); 179 // child animation delay = child index * delay * animation duration 180 assertEquals(0, offsetTime1); 181 assertEquals(1500, offsetTime2); 182 assertEquals(3000, offsetTime3); 183 184 Transformation transformation1 = new Transformation(); 185 Transformation transformation2 = new Transformation(); 186 Transformation transformation3 = new Transformation(); 187 188 // child1 has started animation, child2 and child3 haven't started 189 childAnimation1.getTransformation(startTime + 500, transformation1); 190 childAnimation2.getTransformation(startTime + 500, transformation2); 191 childAnimation3.getTransformation(startTime + 500, transformation3); 192 assertIsRunningAnimation(transformation1.getAlpha()); 193 assertEquals(0.0f, transformation2.getAlpha(), DELTA); 194 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 195 196 // child1 has finished, child2 and child3 haven't started 197 childAnimation1.getTransformation(startTime + 1200, transformation1); 198 childAnimation2.getTransformation(startTime + 1200, transformation2); 199 childAnimation3.getTransformation(startTime + 1200, transformation3); 200 assertEquals(1.0f, transformation1.getAlpha(), DELTA); 201 assertEquals(0.0f, transformation2.getAlpha(), DELTA); 202 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 203 204 // child1 has finished, child2 has started animation, child3 hasn't started. 205 childAnimation1.getTransformation(startTime + 2000, transformation1); 206 childAnimation2.getTransformation(startTime + 2000, transformation2); 207 childAnimation3.getTransformation(startTime + 2000, transformation3); 208 assertEquals(1.0f, transformation1.getAlpha(), DELTA); 209 assertIsRunningAnimation(transformation2.getAlpha()); 210 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 211 212 // child1 and child2 have finished, child3 hasn't started 213 childAnimation1.getTransformation(startTime + 2700, transformation1); 214 childAnimation2.getTransformation(startTime + 2700, transformation2); 215 childAnimation3.getTransformation(startTime + 2700, transformation3); 216 assertEquals(1.0f, transformation1.getAlpha(), DELTA); 217 assertEquals(1.0f, transformation2.getAlpha(), DELTA); 218 assertEquals(0.0f, transformation3.getAlpha(), DELTA); 219 220 // child1 and child2 have finished, child3 has started animation 221 childAnimation1.getTransformation(startTime + 3500, transformation1); 222 childAnimation2.getTransformation(startTime + 3500, transformation2); 223 childAnimation3.getTransformation(startTime + 3500, transformation3); 224 assertIsRunningAnimation(transformation3.getAlpha()); 225 } 226 227 private void assertIsRunningAnimation(float alpha) { 228 assertTrue(alpha > 0.0f); 229 assertTrue(alpha < 1.0f); 230 } 231 232 public void testAccessAnimation() throws InterruptedException { 233 Animation animation = AnimationUtils.loadAnimation(mActivity, R.anim.decelerate_alpha); 234 animation.setFillAfter(true); 235 // duration defined in decelerate_alpha.xml is 2000 236 long duration = 2000; 237 mController.setAnimation(animation); 238 assertSame(animation, mController.getAnimation()); 239 long maxDuration = (long) (DEFAULT_DELAY * INDEX_OF_CHILD3 * duration + duration); 240 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 241 maxDuration); 242 243 Animation childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 244 Animation childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 245 Animation childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 246 assertAnimation(childAnimation1, false, duration); 247 assertAnimation(childAnimation2, false, duration); 248 assertAnimation(childAnimation3, false, duration); 249 250 mController.setAnimation(mActivity, R.anim.layout_anim_controller_animation); 251 Animation actualAnimation = mController.getAnimation(); 252 assertEquals(DURATION, actualAnimation.getDuration()); 253 assertTrue(actualAnimation.getInterpolator() instanceof AccelerateInterpolator); 254 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 255 DEFAULT_MAX_DURATION); 256 257 childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 258 childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 259 childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 260 assertAnimation(childAnimation1, true, DURATION); 261 assertAnimation(childAnimation2, true, DURATION); 262 assertAnimation(childAnimation3, true, DURATION); 263 } 264 265 /** 266 * This method is used for asserting alpha of accelerate and decelerate animations to 267 * make sure their accelerate/decelerate functionalities really work. 268 * @param animation 269 * @param isAccelerate 270 * @param duration 271 */ 272 private void assertAnimation(Animation animation, boolean isAccelerate, long duration) { 273 Transformation transformation = new Transformation(); 274 long baseTime = animation.getStartTime() + animation.getStartOffset(); 275 animation.getTransformation(baseTime, transformation); 276 long step = duration / 4; 277 float alpha1 = transformation.getAlpha(); 278 animation.getTransformation(baseTime + step * 1, transformation); 279 float alpha2 = transformation.getAlpha(); 280 animation.getTransformation(baseTime + step * 2, transformation); 281 float alpha3 = transformation.getAlpha(); 282 animation.getTransformation(baseTime + step * 3, transformation); 283 float alpha4 = transformation.getAlpha(); 284 animation.getTransformation(baseTime + step * 4, transformation); 285 float alpha5 = transformation.getAlpha(); 286 287 // check decelerating delta alpha 288 float delta1 = alpha2 - alpha1; 289 float delta2 = alpha3 - alpha2; 290 float delta3 = alpha4 - alpha3; 291 float delta4 = alpha5 - alpha4; 292 if (isAccelerate) { 293 assertTrue(delta1 < delta2); 294 assertTrue(delta2 < delta3); 295 assertTrue(delta3 < delta4); 296 } else { 297 assertTrue(delta1 > delta2); 298 assertTrue(delta2 > delta3); 299 assertTrue(delta3 > delta4); 300 } 301 } 302 303 public void testAccessInterpolator() throws InterruptedException { 304 DecelerateInterpolator interpolator = new DecelerateInterpolator(1.0f); 305 mController.setInterpolator(interpolator); 306 assertSame(interpolator, mController.getInterpolator()); 307 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 308 DEFAULT_MAX_DURATION); 309 310 Animation childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 311 Animation childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 312 Animation childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 313 314 long delta1 = childAnimation2.getStartOffset() - childAnimation1.getStartOffset(); 315 long delta2 = childAnimation3.getStartOffset() - childAnimation2.getStartOffset(); 316 assertTrue(delta2 < delta1); 317 318 mController.setInterpolator(mActivity, android.R.anim.accelerate_interpolator); 319 assertTrue(mController.getInterpolator() instanceof AccelerateInterpolator); 320 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 321 DEFAULT_MAX_DURATION); 322 323 childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 324 childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 325 childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 326 327 delta1 = childAnimation2.getStartOffset() - childAnimation1.getStartOffset(); 328 delta2 = childAnimation3.getStartOffset() - childAnimation2.getStartOffset(); 329 assertTrue(delta2 > delta1); 330 } 331 332 public void testConstructor() { 333 XmlResourceParser parser = mActivity.getResources().getAnimation( 334 R.anim.accelerate_decelerate_alpha); 335 AttributeSet attrs = Xml.asAttributeSet(parser); 336 new LayoutAnimationController(mActivity, attrs); 337 new LayoutAnimationController(mDefaultAnimation, DEFAULT_DELAY); 338 LayoutAnimationController controller = new LayoutAnimationController(mDefaultAnimation); 339 assertEquals(DEFAULT_DELAY, controller.getDelay()); 340 } 341 342 public void testGetDelayForView() throws Throwable { 343 Animation animation = AnimationUtils.loadAnimation(mActivity, R.anim.decelerate_alpha); 344 animation.setFillAfter(true); 345 MyLayoutAnimationController controller = new MyLayoutAnimationController(animation); 346 347 // child1's animationParams 348 final AbsListView.LayoutParams layoutParams1 = setAnimationParameters(0); 349 // child2's animationParams 350 final AbsListView.LayoutParams layoutParams2 = setAnimationParameters(1); 351 // child3's animationParams 352 final AbsListView.LayoutParams layoutParams3 = setAnimationParameters(2); 353 354 final View child1 = mListView.getChildAt(INDEX_OF_CHILD1); 355 final View child2 = mListView.getChildAt(INDEX_OF_CHILD2); 356 final View child3 = mListView.getChildAt(INDEX_OF_CHILD3); 357 runTestOnUiThread(new Runnable() { 358 public void run() { 359 child1.setLayoutParams(layoutParams1); 360 child2.setLayoutParams(layoutParams2); 361 child3.setLayoutParams(layoutParams3); 362 } 363 }); 364 365 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, controller, 366 DEFAULT_MAX_DURATION); 367 368 assertEquals(0, controller.getDelayForView(child1)); 369 assertEquals(1000, controller.getDelayForView(child2)); 370 assertEquals(2000, controller.getDelayForView(child3)); 371 } 372 373 private AbsListView.LayoutParams setAnimationParameters(int index) { 374 AnimationParameters animationParams = new AnimationParameters(); 375 animationParams.index = index; 376 animationParams.count = 3; 377 final AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams( 378 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 379 layoutParams.layoutAnimationParameters = animationParams; 380 return layoutParams; 381 } 382 383 public void testGetTransformedIndex() { 384 Animation animation = AnimationUtils.loadAnimation(mActivity, R.anim.decelerate_alpha); 385 animation.setFillAfter(true); 386 MyLayoutAnimationController controller = new MyLayoutAnimationController(animation); 387 AnimationParameters animationParams = new AnimationParameters(); 388 animationParams.count = 3; 389 390 // Test getTransformedIndex in ORDER_NORMAL condition, child1_index == 0, child2_index == 1, 391 // child3_index == 2 392 animationParams.index = 0; 393 assertEquals(0, controller.getTransformedIndex(animationParams)); 394 animationParams.index = 1; 395 assertEquals(1, controller.getTransformedIndex(animationParams)); 396 animationParams.index = 2; 397 assertEquals(2, controller.getTransformedIndex(animationParams)); 398 // Test getTransformedIndex in ORDER_REVERSE condition, child1_index == 2, 399 // child2_index == 1, child3_index == 0 400 controller.setOrder(LayoutAnimationController.ORDER_REVERSE); 401 animationParams.index = 0; 402 assertEquals(2, controller.getTransformedIndex(animationParams)); 403 animationParams.index = 1; 404 assertEquals(1, controller.getTransformedIndex(animationParams)); 405 animationParams.index = 2; 406 assertEquals(0, controller.getTransformedIndex(animationParams)); 407 } 408 409 public void testStart() { 410 Animation animation = new ScaleAnimation(0.0f, 10.0f, 0.0f, 20.0f); 411 animation.setStartTime(500); 412 LayoutAnimationController controller = new LayoutAnimationController(animation); 413 414 assertTrue(Animation.START_ON_FIRST_FRAME != controller.getAnimation().getStartTime()); 415 416 controller.start(); 417 assertEquals(Animation.START_ON_FIRST_FRAME, controller.getAnimation().getStartTime()); 418 } 419 420 public void testIsDone() throws InterruptedException { 421 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 422 DEFAULT_MAX_DURATION); 423 assertTrue(mController.isDone()); 424 } 425 426 public void testGetAnimationForView() throws InterruptedException { 427 Animation animation = AnimationUtils.loadAnimation(mActivity, R.anim.decelerate_alpha); 428 animation.setFillAfter(true); 429 mController.setAnimation(animation); 430 AnimationTestUtils.assertRunController(getInstrumentation(), mListView, mController, 431 DEFAULT_MAX_DURATION); 432 Animation childAnimation1 = mListView.getChildAt(INDEX_OF_CHILD1).getAnimation(); 433 Animation childAnimation2 = mListView.getChildAt(INDEX_OF_CHILD2).getAnimation(); 434 Animation childAnimation3 = mListView.getChildAt(INDEX_OF_CHILD3).getAnimation(); 435 // duration defined in decelerate_alpha.xml is 2000 436 long duration = 2000; 437 assertAnimation(childAnimation1, false, duration); 438 assertAnimation(childAnimation2, false, duration); 439 assertAnimation(childAnimation3, false, duration); 440 assertEquals(0, childAnimation1.getStartOffset()); 441 assertEquals(1000, childAnimation2.getStartOffset()); 442 assertEquals(2000, childAnimation3.getStartOffset()); 443 } 444 445 public void testWillOverlap() { 446 LayoutAnimationController controller = new LayoutAnimationController(mDefaultAnimation); 447 448 controller.setDelay(0.5f); 449 assertTrue(controller.willOverlap()); 450 451 controller.setDelay(1.0f); 452 assertFalse(controller.willOverlap()); 453 454 controller.setDelay(1.5f); 455 assertFalse(controller.willOverlap()); 456 } 457 458 private class MyLayoutAnimationController extends LayoutAnimationController { 459 public MyLayoutAnimationController(Animation animation) { 460 super(animation); 461 } 462 463 protected int getTransformedIndex(AnimationParameters params) { 464 return super.getTransformedIndex(params); 465 } 466 467 protected long getDelayForView(View view) { 468 return super.getDelayForView(view); 469 } 470 } 471} 472