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 android.animation.Animator; 19 import android.animation.AnimatorListenerAdapter; 20 import android.animation.ArgbEvaluator; 21 import android.animation.Keyframe; 22 import android.animation.ObjectAnimator; 23 import android.animation.PropertyValuesHolder; 24 import android.animation.ValueAnimator; 25 import android.graphics.drawable.ShapeDrawable; 26 import android.test.ActivityInstrumentationTestCase2; 27 import android.util.Property; 28 import android.view.View; 29 import android.view.animation.AccelerateInterpolator; 30 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 34 public class PropertyValuesHolderTest extends 35 ActivityInstrumentationTestCase2<AnimationActivity> { 36 private AnimationActivity mActivity; 37 private Animator mAnimator; 38 private long mDuration = 1000; 39 private float mStartY; 40 private float mEndY; 41 private Object mObject; 42 private String mProperty; 43 PropertyValuesHolderTest()44 public PropertyValuesHolderTest() { 45 super(AnimationActivity.class); 46 } 47 setUp()48 public void setUp() throws Exception { 49 super.setUp(); 50 setActivityInitialTouchMode(false); 51 mActivity = getActivity(); 52 mAnimator = mActivity.createAnimatorWithDuration(mDuration); 53 mProperty = "y"; 54 mStartY = mActivity.mStartY; 55 mEndY = mActivity.mStartY + mActivity.mDeltaY; 56 mObject = mActivity.view.newBall; 57 } 58 testGetPropertyName()59 public void testGetPropertyName() { 60 float[] values = {mStartY, mEndY}; 61 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values); 62 assertEquals(mProperty, pVHolder.getPropertyName()); 63 } 64 testSetPropertyName()65 public void testSetPropertyName() { 66 float[] values = {mStartY, mEndY}; 67 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat("", values); 68 pVHolder.setPropertyName(mProperty); 69 assertEquals(mProperty, pVHolder.getPropertyName()); 70 } 71 testClone()72 public void testClone() { 73 float[] values = {mStartY, mEndY}; 74 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values); 75 PropertyValuesHolder cloneHolder = pVHolder.clone(); 76 assertEquals(pVHolder.getPropertyName(), cloneHolder.getPropertyName()); 77 } 78 testSetValues()79 public void testSetValues() throws Throwable { 80 float[] dummyValues = {100, 150}; 81 float[] values = {mStartY, mEndY}; 82 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, dummyValues); 83 pVHolder.setFloatValues(values); 84 85 ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 86 assertTrue(objAnimator != null); 87 setAnimatorProperties(objAnimator); 88 89 startAnimation(objAnimator); 90 assertTrue(objAnimator != null); 91 float[] yArray = getYPosition(); 92 assertResults(yArray, mStartY, mEndY); 93 } 94 createAnimator(Keyframe... keyframes)95 private ObjectAnimator createAnimator(Keyframe... keyframes) { 96 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofKeyframe(mProperty, keyframes); 97 ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 98 objAnimator.setDuration(mDuration); 99 objAnimator.setInterpolator(new AccelerateInterpolator()); 100 return objAnimator; 101 } 102 waitUntilFinished(ObjectAnimator objectAnimator, long timeoutMilliseconds)103 private void waitUntilFinished(ObjectAnimator objectAnimator, long timeoutMilliseconds) 104 throws InterruptedException { 105 final CountDownLatch latch = new CountDownLatch(1); 106 objectAnimator.addListener(new AnimatorListenerAdapter() { 107 @Override 108 public void onAnimationEnd(Animator animation) { 109 super.onAnimationEnd(animation); 110 latch.countDown(); 111 } 112 }); 113 latch.await(timeoutMilliseconds, TimeUnit.MILLISECONDS); 114 getInstrumentation().waitForIdleSync(); 115 } 116 setTarget(final Animator animator, final Object target)117 private void setTarget(final Animator animator, final Object target) throws Throwable { 118 runTestOnUiThread(new Runnable() { 119 @Override 120 public void run() { 121 animator.setTarget(target); 122 } 123 }); 124 } 125 startSingleAnimation(final Animator animator)126 private void startSingleAnimation(final Animator animator) throws Throwable { 127 runTestOnUiThread(new Runnable() { 128 @Override 129 public void run() { 130 mActivity.startSingleAnimation(animator); 131 } 132 }); 133 } 134 testResetValues()135 public void testResetValues() throws Throwable { 136 final float initialY = mActivity.view.newBall.getY(); 137 Keyframe emptyKeyframe1 = Keyframe.ofFloat(.0f); 138 ObjectAnimator objAnimator1 = createAnimator(emptyKeyframe1, Keyframe.ofFloat(1f, 100f)); 139 startSingleAnimation(objAnimator1); 140 assertTrue("Keyframe should be assigned a value", emptyKeyframe1.hasValue()); 141 assertEquals("Keyframe should get the value from the target", emptyKeyframe1.getValue(), 142 initialY); 143 waitUntilFinished(objAnimator1, mDuration * 2); 144 assertEquals(100f, mActivity.view.newBall.getY()); 145 startSingleAnimation(objAnimator1); 146 waitUntilFinished(objAnimator1, mDuration * 2); 147 148 // run another ObjectAnimator that will move the Y value to something else 149 Keyframe emptyKeyframe2 = Keyframe.ofFloat(.0f); 150 ObjectAnimator objAnimator2 = createAnimator(emptyKeyframe2, Keyframe.ofFloat(1f, 200f)); 151 startSingleAnimation(objAnimator2); 152 assertTrue("Keyframe should be assigned a value", emptyKeyframe2.hasValue()); 153 assertEquals("Keyframe should get the value from the target", emptyKeyframe2.getValue(), 100f); 154 waitUntilFinished(objAnimator2, mDuration * 2); 155 assertEquals(200f, mActivity.view.newBall.getY()); 156 157 // re-run first object animator. since its target did not change, it should have the same 158 // start value for kf1 159 startSingleAnimation(objAnimator1); 160 assertEquals(emptyKeyframe1.getValue(), initialY); 161 waitUntilFinished(objAnimator1, mDuration * 2); 162 163 Keyframe fullKeyframe = Keyframe.ofFloat(.0f, 333f); 164 ObjectAnimator objAnimator3 = createAnimator(fullKeyframe, Keyframe.ofFloat(1f, 500f)); 165 startSingleAnimation(objAnimator3); 166 assertEquals("When keyframe has value, should not be assigned from the target object", 167 fullKeyframe.getValue(), 333f); 168 waitUntilFinished(objAnimator3, mDuration * 2); 169 170 // now, null out the target of the first animator 171 float updatedY = mActivity.view.newBall.getY(); 172 setTarget(objAnimator1, null); 173 startSingleAnimation(objAnimator1); 174 assertTrue("Keyframe should get a value", emptyKeyframe1.hasValue()); 175 assertEquals("Keyframe should get the updated Y value", emptyKeyframe1.getValue(), updatedY); 176 waitUntilFinished(objAnimator1, mDuration * 2); 177 assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY()); 178 179 // now, reset the target of the fully defined animation. 180 setTarget(objAnimator3, null); 181 startSingleAnimation(objAnimator3); 182 assertEquals("When keyframe is fully defined, its value should not change when target is" 183 + " reset", fullKeyframe.getValue(), 333f); 184 waitUntilFinished(objAnimator3, mDuration * 2); 185 186 // run the other one to change Y value 187 startSingleAnimation(objAnimator2); 188 waitUntilFinished(objAnimator2, mDuration * 2); 189 // now, set another target w/ the same View type. it should still reset 190 ShapeHolder view = new ShapeHolder(new ShapeDrawable()); 191 updatedY = mActivity.view.newBall.getY(); 192 setTarget(objAnimator1, view); 193 startSingleAnimation(objAnimator1); 194 assertTrue("Keyframe should get a value when target is set to another view of the same" 195 + " class", emptyKeyframe1.hasValue()); 196 assertEquals("Keyframe should get the updated Y value when target is set to another view" 197 + " of the same class", emptyKeyframe1.getValue(), updatedY); 198 waitUntilFinished(objAnimator1, mDuration * 2); 199 assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY()); 200 } 201 testOffloat()202 public void testOffloat() throws Throwable { 203 float[] values = {mStartY, mEndY}; 204 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values); 205 assertNotNull(pVHolder); 206 ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 207 assertTrue(objAnimator != null); 208 209 setAnimatorProperties(objAnimator); 210 startAnimation(objAnimator); 211 assertTrue(objAnimator != null); 212 float[] yArray = getYPosition(); 213 assertResults(yArray, mStartY, mEndY); 214 } 215 testOfFloat_Property()216 public void testOfFloat_Property() throws Throwable { 217 float[] values = {mStartY, mEndY}; 218 ShapeHolderYProperty property=new ShapeHolderYProperty(ShapeHolder.class.getClass(),"y"); 219 property.setObject(mObject); 220 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(property, values); 221 assertNotNull(pVHolder); 222 ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 223 assertTrue(objAnimator != null); 224 225 setAnimatorProperties(objAnimator); 226 startAnimation(objAnimator); 227 assertTrue(objAnimator != null); 228 float[] yArray = getYPosition(); 229 assertResults(yArray, mStartY, mEndY); 230 } 231 testOfInt()232 public void testOfInt() throws Throwable { 233 int start = 0; 234 int end = 10; 235 int[] values = {start, end}; 236 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofInt(mProperty, values); 237 assertNotNull(pVHolder); 238 final ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 239 assertTrue(objAnimator != null); 240 setAnimatorProperties(objAnimator); 241 this.runTestOnUiThread(new Runnable(){ 242 public void run() { 243 objAnimator.start(); 244 } 245 }); 246 Thread.sleep(1000); 247 assertTrue(objAnimator.isRunning()); 248 Integer animatedValue = (Integer) objAnimator.getAnimatedValue(); 249 assertTrue(animatedValue >= start); 250 assertTrue(animatedValue <= end); 251 } 252 testOfInt_Property()253 public void testOfInt_Property() throws Throwable{ 254 Object object = mActivity.view; 255 String property = "backgroundColor"; 256 int startColor = mActivity.view.RED; 257 int endColor = mActivity.view.BLUE; 258 int values[] = {startColor, endColor}; 259 260 ViewColorProperty colorProperty=new ViewColorProperty(Integer.class.getClass(),property); 261 colorProperty.setObject(object); 262 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofInt(colorProperty, values); 263 assertNotNull(pVHolder); 264 265 ObjectAnimator colorAnimator = ObjectAnimator.ofPropertyValuesHolder(object,pVHolder); 266 colorAnimator.setDuration(1000); 267 colorAnimator.setEvaluator(new ArgbEvaluator()); 268 colorAnimator.setRepeatCount(ValueAnimator.INFINITE); 269 colorAnimator.setRepeatMode(ValueAnimator.REVERSE); 270 271 ObjectAnimator objectAnimator = (ObjectAnimator) mActivity.createAnimatorWithDuration( 272 mDuration); 273 startAnimation(objectAnimator, colorAnimator); 274 Thread.sleep(1000); 275 Integer i = (Integer) colorAnimator.getAnimatedValue(); 276 //We are going from less negative value to a more negative value 277 assertTrue(i.intValue() <= startColor); 278 assertTrue(endColor <= i.intValue()); 279 } 280 testSetProperty()281 public void testSetProperty() throws Throwable { 282 float[] values = {mStartY, mEndY}; 283 ShapeHolderYProperty property=new ShapeHolderYProperty(ShapeHolder.class.getClass(),"y"); 284 property.setObject(mObject); 285 PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat("", values); 286 pVHolder.setProperty(property); 287 ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder); 288 setAnimatorProperties(objAnimator); 289 startAnimation(objAnimator); 290 assertTrue(objAnimator != null); 291 float[] yArray = getYPosition(); 292 assertResults(yArray, mStartY, mEndY); 293 } 294 295 class ShapeHolderYProperty extends Property { 296 private ShapeHolder shapeHolder ; 297 private Class type = Float.class.getClass(); 298 private String name = "y"; 299 @SuppressWarnings("unchecked") ShapeHolderYProperty(Class type, String name)300 public ShapeHolderYProperty(Class type, String name) throws Exception { 301 super(Float.class, name ); 302 if(!( type.equals(this.type) || ( name.equals(this.name))) ){ 303 throw new Exception("Type or name provided does not match with " + 304 this.type.getName() + " or " + this.name); 305 } 306 } 307 setObject(Object object)308 public void setObject(Object object){ 309 shapeHolder = (ShapeHolder) object; 310 } 311 312 @Override get(Object object)313 public Object get(Object object) { 314 return shapeHolder; 315 } 316 317 @Override getName()318 public String getName() { 319 return "y"; 320 } 321 322 @Override getType()323 public Class getType() { 324 return super.getType(); 325 } 326 327 @Override isReadOnly()328 public boolean isReadOnly() { 329 return false; 330 } 331 332 @Override set(Object object, Object value)333 public void set(Object object, Object value) { 334 shapeHolder.setY((Float)value); 335 } 336 337 } 338 339 class ViewColorProperty extends Property { 340 private View view ; 341 private Class type = Integer.class.getClass(); 342 private String name = "backgroundColor"; 343 @SuppressWarnings("unchecked") ViewColorProperty(Class type, String name)344 public ViewColorProperty(Class type, String name) throws Exception { 345 super(Integer.class, name ); 346 if(!( type.equals(this.type) || ( name.equals(this.name))) ){ 347 throw new Exception("Type or name provided does not match with " + 348 this.type.getName() + " or " + this.name); 349 } 350 } 351 setObject(Object object)352 public void setObject(Object object){ 353 view = (View) object; 354 } 355 356 @Override get(Object object)357 public Object get(Object object) { 358 return view; 359 } 360 361 @Override getName()362 public String getName() { 363 return name; 364 } 365 366 @Override getType()367 public Class getType() { 368 return super.getType(); 369 } 370 371 @Override isReadOnly()372 public boolean isReadOnly() { 373 return false; 374 } 375 376 @Override set(Object object, Object value)377 public void set(Object object, Object value) { 378 view.setBackgroundColor((Integer)value); 379 } 380 } 381 setAnimatorProperties(ObjectAnimator objAnimator)382 private void setAnimatorProperties(ObjectAnimator objAnimator) { 383 objAnimator.setDuration(mDuration); 384 objAnimator.setRepeatCount(ValueAnimator.INFINITE); 385 objAnimator.setInterpolator(new AccelerateInterpolator()); 386 objAnimator.setRepeatMode(ValueAnimator.REVERSE); 387 } 388 getYPosition()389 public float[] getYPosition() throws Throwable{ 390 float[] yArray = new float[3]; 391 for(int i = 0; i < 3; i++) { 392 float y = mActivity.view.newBall.getY(); 393 yArray[i] = y; 394 Thread.sleep(300); 395 } 396 return yArray; 397 } 398 assertResults(float[] yArray,float startY, float endY)399 public void assertResults(float[] yArray,float startY, float endY) { 400 for(int i = 0; i < 3; i++){ 401 float y = yArray[i]; 402 assertTrue(y >= startY); 403 assertTrue(y <= endY); 404 if(i < 2) { 405 float yNext = yArray[i+1]; 406 assertTrue(y != yNext); 407 } 408 } 409 } 410 startAnimation(final Animator animator)411 private void startAnimation(final Animator animator) throws Throwable { 412 this.runTestOnUiThread(new Runnable() { 413 public void run() { 414 mActivity.startAnimation(animator); 415 } 416 }); 417 } 418 startAnimation(final ObjectAnimator mObjectAnimator, final ObjectAnimator colorAnimator)419 private void startAnimation(final ObjectAnimator mObjectAnimator, 420 final ObjectAnimator colorAnimator) throws Throwable { 421 Thread mAnimationRunnable = new Thread() { 422 public void run() { 423 mActivity.startAnimation(mObjectAnimator, colorAnimator); 424 } 425 }; 426 this.runTestOnUiThread(mAnimationRunnable); 427 } 428 } 429 430