Home | History | Annotate | Download | only in cts
      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 
     44     public PropertyValuesHolderTest() {
     45         super(AnimationActivity.class);
     46     }
     47 
     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 
     59     public void testGetPropertyName() {
     60         float[] values = {mStartY, mEndY};
     61         PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values);
     62         assertEquals(mProperty, pVHolder.getPropertyName());
     63     }
     64 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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")
    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 
    308         public void setObject(Object object){
    309             shapeHolder = (ShapeHolder) object;
    310         }
    311 
    312         @Override
    313         public Object get(Object object) {
    314             return shapeHolder;
    315         }
    316 
    317         @Override
    318         public String getName() {
    319             return "y";
    320         }
    321 
    322         @Override
    323         public Class getType() {
    324             return super.getType();
    325         }
    326 
    327         @Override
    328         public boolean isReadOnly() {
    329             return false;
    330         }
    331 
    332         @Override
    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")
    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 
    352         public void setObject(Object object){
    353             view = (View) object;
    354         }
    355 
    356         @Override
    357         public Object get(Object object) {
    358             return view;
    359         }
    360 
    361         @Override
    362         public String getName() {
    363             return name;
    364         }
    365 
    366         @Override
    367         public Class getType() {
    368             return super.getType();
    369         }
    370 
    371         @Override
    372         public boolean isReadOnly() {
    373             return false;
    374         }
    375 
    376         @Override
    377         public void set(Object object, Object value) {
    378             view.setBackgroundColor((Integer)value);
    379         }
    380     }
    381 
    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 
    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 
    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 
    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 
    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