Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2010 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 
     17 package android.animation;
     18 
     19 import android.annotation.CallSuper;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.graphics.Path;
     23 import android.graphics.PointF;
     24 import android.util.Log;
     25 import android.util.Property;
     26 import android.view.animation.AccelerateDecelerateInterpolator;
     27 
     28 import java.lang.ref.WeakReference;
     29 
     30 /**
     31  * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
     32  * The constructors of this class take parameters to define the target object that will be animated
     33  * as well as the name of the property that will be animated. Appropriate set/get functions
     34  * are then determined internally and the animation will call these functions as necessary to
     35  * animate the property.
     36  *
     37  * <p>Animators can be created from either code or resource files, as shown here:</p>
     38  *
     39  * {@sample development/samples/ApiDemos/res/anim/object_animator.xml ObjectAnimatorResources}
     40  *
     41  * <p>Starting from API 23, it is possible to use {@link PropertyValuesHolder} and
     42  * {@link Keyframe} in resource files to create more complex animations. Using PropertyValuesHolders
     43  * allows animators to animate several properties in parallel, as shown in this sample:</p>
     44  *
     45  * {@sample development/samples/ApiDemos/res/anim/object_animator_pvh.xml
     46  * PropertyValuesHolderResources}
     47  *
     48  * <p>Using Keyframes allows animations to follow more complex paths from the start
     49  * to the end values. Note that you can specify explicit fractional values (from 0 to 1) for
     50  * each keyframe to determine when, in the overall duration, the animation should arrive at that
     51  * value. Alternatively, you can leave the fractions off and the keyframes will be equally
     52  * distributed within the total duration. Also, a keyframe with no value will derive its value
     53  * from the target object when the animator starts, just like animators with only one
     54  * value specified. In addition, an optional interpolator can be specified. The interpolator will
     55  * be applied on the interval between the keyframe that the interpolator is set on and the previous
     56  * keyframe. When no interpolator is supplied, the default {@link AccelerateDecelerateInterpolator}
     57  * will be used. </p>
     58  *
     59  * {@sample development/samples/ApiDemos/res/anim/object_animator_pvh_kf_interpolated.xml KeyframeResources}
     60  *
     61  * <div class="special reference">
     62  * <h3>Developer Guides</h3>
     63  * <p>For more information about animating with {@code ObjectAnimator}, read the
     64  * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#object-animator">Property
     65  * Animation</a> developer guide.</p>
     66  * </div>
     67  *
     68  * @see #setPropertyName(String)
     69  *
     70  */
     71 public final class ObjectAnimator extends ValueAnimator {
     72     private static final String LOG_TAG = "ObjectAnimator";
     73 
     74     private static final boolean DBG = false;
     75 
     76     /**
     77      * A weak reference to the target object on which the property exists, set
     78      * in the constructor. We'll cancel the animation if this goes away.
     79      */
     80     private WeakReference<Object> mTarget;
     81 
     82     private String mPropertyName;
     83 
     84     private Property mProperty;
     85 
     86     private boolean mAutoCancel = false;
     87 
     88     /**
     89      * Sets the name of the property that will be animated. This name is used to derive
     90      * a setter function that will be called to set animated values.
     91      * For example, a property name of <code>foo</code> will result
     92      * in a call to the function <code>setFoo()</code> on the target object. If either
     93      * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
     94      * also be derived and called.
     95      *
     96      * <p>For best performance of the mechanism that calls the setter function determined by the
     97      * name of the property being animated, use <code>float</code> or <code>int</code> typed values,
     98      * and make the setter function for those properties have a <code>void</code> return value. This
     99      * will cause the code to take an optimized path for these constrained circumstances. Other
    100      * property types and return types will work, but will have more overhead in processing
    101      * the requests due to normal reflection mechanisms.</p>
    102      *
    103      * <p>Note that the setter function derived from this property name
    104      * must take the same parameter type as the
    105      * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
    106      * the setter function will fail.</p>
    107      *
    108      * <p>If this ObjectAnimator has been set up to animate several properties together,
    109      * using more than one PropertyValuesHolder objects, then setting the propertyName simply
    110      * sets the propertyName in the first of those PropertyValuesHolder objects.</p>
    111      *
    112      * @param propertyName The name of the property being animated. Should not be null.
    113      */
    114     public void setPropertyName(@NonNull String propertyName) {
    115         // mValues could be null if this is being constructed piecemeal. Just record the
    116         // propertyName to be used later when setValues() is called if so.
    117         if (mValues != null) {
    118             PropertyValuesHolder valuesHolder = mValues[0];
    119             String oldName = valuesHolder.getPropertyName();
    120             valuesHolder.setPropertyName(propertyName);
    121             mValuesMap.remove(oldName);
    122             mValuesMap.put(propertyName, valuesHolder);
    123         }
    124         mPropertyName = propertyName;
    125         // New property/values/target should cause re-initialization prior to starting
    126         mInitialized = false;
    127     }
    128 
    129     /**
    130      * Sets the property that will be animated. Property objects will take precedence over
    131      * properties specified by the {@link #setPropertyName(String)} method. Animations should
    132      * be set up to use one or the other, not both.
    133      *
    134      * @param property The property being animated. Should not be null.
    135      */
    136     public void setProperty(@NonNull Property property) {
    137         // mValues could be null if this is being constructed piecemeal. Just record the
    138         // propertyName to be used later when setValues() is called if so.
    139         if (mValues != null) {
    140             PropertyValuesHolder valuesHolder = mValues[0];
    141             String oldName = valuesHolder.getPropertyName();
    142             valuesHolder.setProperty(property);
    143             mValuesMap.remove(oldName);
    144             mValuesMap.put(mPropertyName, valuesHolder);
    145         }
    146         if (mProperty != null) {
    147             mPropertyName = property.getName();
    148         }
    149         mProperty = property;
    150         // New property/values/target should cause re-initialization prior to starting
    151         mInitialized = false;
    152     }
    153 
    154     /**
    155      * Gets the name of the property that will be animated. This name will be used to derive
    156      * a setter function that will be called to set animated values.
    157      * For example, a property name of <code>foo</code> will result
    158      * in a call to the function <code>setFoo()</code> on the target object. If either
    159      * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
    160      * also be derived and called.
    161      *
    162      * <p>If this animator was created with a {@link Property} object instead of the
    163      * string name of a property, then this method will return the {@link
    164      * Property#getName() name} of that Property object instead. If this animator was
    165      * created with one or more {@link PropertyValuesHolder} objects, then this method
    166      * will return the {@link PropertyValuesHolder#getPropertyName() name} of that
    167      * object (if there was just one) or a comma-separated list of all of the
    168      * names (if there are more than one).</p>
    169      */
    170     @Nullable
    171     public String getPropertyName() {
    172         String propertyName = null;
    173         if (mPropertyName != null) {
    174             propertyName = mPropertyName;
    175         } else if (mProperty != null) {
    176             propertyName = mProperty.getName();
    177         } else if (mValues != null && mValues.length > 0) {
    178             for (int i = 0; i < mValues.length; ++i) {
    179                 if (i == 0) {
    180                     propertyName = "";
    181                 } else {
    182                     propertyName += ",";
    183                 }
    184                 propertyName += mValues[i].getPropertyName();
    185             }
    186         }
    187         return propertyName;
    188     }
    189 
    190     @Override
    191     String getNameForTrace() {
    192         return "animator:" + getPropertyName();
    193     }
    194 
    195     /**
    196      * Creates a new ObjectAnimator object. This default constructor is primarily for
    197      * use internally; the other constructors which take parameters are more generally
    198      * useful.
    199      */
    200     public ObjectAnimator() {
    201     }
    202 
    203     /**
    204      * Private utility constructor that initializes the target object and name of the
    205      * property being animated.
    206      *
    207      * @param target The object whose property is to be animated. This object should
    208      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    209      * the value of the <code>propertyName</code> parameter.
    210      * @param propertyName The name of the property being animated.
    211      */
    212     private ObjectAnimator(Object target, String propertyName) {
    213         setTarget(target);
    214         setPropertyName(propertyName);
    215     }
    216 
    217     /**
    218      * Private utility constructor that initializes the target object and property being animated.
    219      *
    220      * @param target The object whose property is to be animated.
    221      * @param property The property being animated.
    222      */
    223     private <T> ObjectAnimator(T target, Property<T, ?> property) {
    224         setTarget(target);
    225         setProperty(property);
    226     }
    227 
    228     /**
    229      * Constructs and returns an ObjectAnimator that animates between int values. A single
    230      * value implies that that value is the one being animated to, in which case the start value
    231      * will be derived from the property being animated and the target object when {@link #start()}
    232      * is called for the first time. Two values imply starting and ending values. More than two
    233      * values imply a starting value, values to animate through along the way, and an ending value
    234      * (these values will be distributed evenly across the duration of the animation).
    235      *
    236      * @param target The object whose property is to be animated. This object should
    237      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    238      * the value of the <code>propertyName</code> parameter.
    239      * @param propertyName The name of the property being animated.
    240      * @param values A set of values that the animation will animate between over time.
    241      * @return An ObjectAnimator object that is set up to animate between the given values.
    242      */
    243     public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
    244         ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    245         anim.setIntValues(values);
    246         return anim;
    247     }
    248 
    249     /**
    250      * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
    251      * using two properties. A <code>Path</code></> animation moves in two dimensions, animating
    252      * coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    253      * coordinates are integers that are set to separate properties designated by
    254      * <code>xPropertyName</code> and <code>yPropertyName</code>.
    255      *
    256      * @param target The object whose properties are to be animated. This object should
    257      *               have public methods on it called <code>setNameX()</code> and
    258      *               <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code>
    259      *               are the value of <code>xPropertyName</code> and <code>yPropertyName</code>
    260      *               parameters, respectively.
    261      * @param xPropertyName The name of the property for the x coordinate being animated.
    262      * @param yPropertyName The name of the property for the y coordinate being animated.
    263      * @param path The <code>Path</code> to animate values along.
    264      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    265      */
    266     public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName,
    267             Path path) {
    268         PathKeyframes keyframes = KeyframeSet.ofPath(path);
    269         PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName,
    270                 keyframes.createXIntKeyframes());
    271         PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName,
    272                 keyframes.createYIntKeyframes());
    273         return ofPropertyValuesHolder(target, x, y);
    274     }
    275 
    276     /**
    277      * Constructs and returns an ObjectAnimator that animates between int values. A single
    278      * value implies that that value is the one being animated to, in which case the start value
    279      * will be derived from the property being animated and the target object when {@link #start()}
    280      * is called for the first time. Two values imply starting and ending values. More than two
    281      * values imply a starting value, values to animate through along the way, and an ending value
    282      * (these values will be distributed evenly across the duration of the animation).
    283      *
    284      * @param target The object whose property is to be animated.
    285      * @param property The property being animated.
    286      * @param values A set of values that the animation will animate between over time.
    287      * @return An ObjectAnimator object that is set up to animate between the given values.
    288      */
    289     public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> property, int... values) {
    290         ObjectAnimator anim = new ObjectAnimator(target, property);
    291         anim.setIntValues(values);
    292         return anim;
    293     }
    294 
    295     /**
    296      * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
    297      * using two properties.  A <code>Path</code></> animation moves in two dimensions, animating
    298      * coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    299      * coordinates are integers that are set to separate properties, <code>xProperty</code> and
    300      * <code>yProperty</code>.
    301      *
    302      * @param target The object whose properties are to be animated.
    303      * @param xProperty The property for the x coordinate being animated.
    304      * @param yProperty The property for the y coordinate being animated.
    305      * @param path The <code>Path</code> to animate values along.
    306      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    307      */
    308     public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
    309             Property<T, Integer> yProperty, Path path) {
    310         PathKeyframes keyframes = KeyframeSet.ofPath(path);
    311         PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty,
    312                 keyframes.createXIntKeyframes());
    313         PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty,
    314                 keyframes.createYIntKeyframes());
    315         return ofPropertyValuesHolder(target, x, y);
    316     }
    317 
    318     /**
    319      * Constructs and returns an ObjectAnimator that animates over int values for a multiple
    320      * parameters setter. Only public methods that take only int parameters are supported.
    321      * Each <code>int[]</code> contains a complete set of parameters to the setter method.
    322      * At least two <code>int[]</code> values must be provided, a start and end. More than two
    323      * values imply a starting value, values to animate through along the way, and an ending
    324      * value (these values will be distributed evenly across the duration of the animation).
    325      *
    326      * @param target The object whose property is to be animated. This object may
    327      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    328      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    329      * be the case-sensitive complete name of the public setter method.
    330      * @param propertyName The name of the property being animated or the name of the setter method.
    331      * @param values A set of values that the animation will animate between over time.
    332      * @return An ObjectAnimator object that is set up to animate between the given values.
    333      */
    334     public static ObjectAnimator ofMultiInt(Object target, String propertyName, int[][] values) {
    335         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, values);
    336         return ofPropertyValuesHolder(target, pvh);
    337     }
    338 
    339     /**
    340      * Constructs and returns an ObjectAnimator that animates the target using a multi-int setter
    341      * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions,
    342      * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    343      * coordinates are integer x and y coordinates used in the first and second parameter of the
    344      * setter, respectively.
    345      *
    346      * @param target The object whose property is to be animated. This object may
    347      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    348      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    349      * be the case-sensitive complete name of the public setter method.
    350      * @param propertyName The name of the property being animated or the name of the setter method.
    351      * @param path The <code>Path</code> to animate values along.
    352      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    353      */
    354     public static ObjectAnimator ofMultiInt(Object target, String propertyName, Path path) {
    355         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, path);
    356         return ofPropertyValuesHolder(target, pvh);
    357     }
    358 
    359     /**
    360      * Constructs and returns an ObjectAnimator that animates over values for a multiple int
    361      * parameters setter. Only public methods that take only int parameters are supported.
    362      * <p>At least two values must be provided, a start and end. More than two
    363      * values imply a starting value, values to animate through along the way, and an ending
    364      * value (these values will be distributed evenly across the duration of the animation).</p>
    365      *
    366      * @param target The object whose property is to be animated. This object may
    367      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    368      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    369      * be the case-sensitive complete name of the public setter method.
    370      * @param propertyName The name of the property being animated or the name of the setter method.
    371      * @param converter Converts T objects into int parameters for the multi-value setter.
    372      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    373      * provide the necessary interpolation between the Object values to derive the animated
    374      * value.
    375      * @param values A set of values that the animation will animate between over time.
    376      * @return An ObjectAnimator object that is set up to animate between the given values.
    377      */
    378     @SafeVarargs
    379     public static <T> ObjectAnimator ofMultiInt(Object target, String propertyName,
    380             TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values) {
    381         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, converter,
    382                 evaluator, values);
    383         return ObjectAnimator.ofPropertyValuesHolder(target, pvh);
    384     }
    385 
    386     /**
    387      * Constructs and returns an ObjectAnimator that animates between color values. A single
    388      * value implies that that value is the one being animated to, in which case the start value
    389      * will be derived from the property being animated and the target object when {@link #start()}
    390      * is called for the first time. Two values imply starting and ending values. More than two
    391      * values imply a starting value, values to animate through along the way, and an ending value
    392      * (these values will be distributed evenly across the duration of the animation).
    393      *
    394      * @param target The object whose property is to be animated. This object should
    395      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    396      * the value of the <code>propertyName</code> parameter.
    397      * @param propertyName The name of the property being animated.
    398      * @param values A set of values that the animation will animate between over time.
    399      * @return An ObjectAnimator object that is set up to animate between the given values.
    400      */
    401     public static ObjectAnimator ofArgb(Object target, String propertyName, int... values) {
    402         ObjectAnimator animator = ofInt(target, propertyName, values);
    403         animator.setEvaluator(ArgbEvaluator.getInstance());
    404         return animator;
    405     }
    406 
    407     /**
    408      * Constructs and returns an ObjectAnimator that animates between color values. A single
    409      * value implies that that value is the one being animated to, in which case the start value
    410      * will be derived from the property being animated and the target object when {@link #start()}
    411      * is called for the first time. Two values imply starting and ending values. More than two
    412      * values imply a starting value, values to animate through along the way, and an ending value
    413      * (these values will be distributed evenly across the duration of the animation).
    414      *
    415      * @param target The object whose property is to be animated.
    416      * @param property The property being animated.
    417      * @param values A set of values that the animation will animate between over time.
    418      * @return An ObjectAnimator object that is set up to animate between the given values.
    419      */
    420     public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property,
    421             int... values) {
    422         ObjectAnimator animator = ofInt(target, property, values);
    423         animator.setEvaluator(ArgbEvaluator.getInstance());
    424         return animator;
    425     }
    426 
    427     /**
    428      * Constructs and returns an ObjectAnimator that animates between float values. A single
    429      * value implies that that value is the one being animated to, in which case the start value
    430      * will be derived from the property being animated and the target object when {@link #start()}
    431      * is called for the first time. Two values imply starting and ending values. More than two
    432      * values imply a starting value, values to animate through along the way, and an ending value
    433      * (these values will be distributed evenly across the duration of the animation).
    434      *
    435      * @param target The object whose property is to be animated. This object should
    436      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    437      * the value of the <code>propertyName</code> parameter.
    438      * @param propertyName The name of the property being animated.
    439      * @param values A set of values that the animation will animate between over time.
    440      * @return An ObjectAnimator object that is set up to animate between the given values.
    441      */
    442     public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
    443         ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    444         anim.setFloatValues(values);
    445         return anim;
    446     }
    447 
    448     /**
    449      * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
    450      * using two properties. A <code>Path</code></> animation moves in two dimensions, animating
    451      * coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    452      * coordinates are floats that are set to separate properties designated by
    453      * <code>xPropertyName</code> and <code>yPropertyName</code>.
    454      *
    455      * @param target The object whose properties are to be animated. This object should
    456      *               have public methods on it called <code>setNameX()</code> and
    457      *               <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code>
    458      *               are the value of the <code>xPropertyName</code> and <code>yPropertyName</code>
    459      *               parameters, respectively.
    460      * @param xPropertyName The name of the property for the x coordinate being animated.
    461      * @param yPropertyName The name of the property for the y coordinate being animated.
    462      * @param path The <code>Path</code> to animate values along.
    463      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    464      */
    465     public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName,
    466             Path path) {
    467         PathKeyframes keyframes = KeyframeSet.ofPath(path);
    468         PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName,
    469                 keyframes.createXFloatKeyframes());
    470         PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName,
    471                 keyframes.createYFloatKeyframes());
    472         return ofPropertyValuesHolder(target, x, y);
    473     }
    474 
    475     /**
    476      * Constructs and returns an ObjectAnimator that animates between float values. A single
    477      * value implies that that value is the one being animated to, in which case the start value
    478      * will be derived from the property being animated and the target object when {@link #start()}
    479      * is called for the first time. Two values imply starting and ending values. More than two
    480      * values imply a starting value, values to animate through along the way, and an ending value
    481      * (these values will be distributed evenly across the duration of the animation).
    482      *
    483      * @param target The object whose property is to be animated.
    484      * @param property The property being animated.
    485      * @param values A set of values that the animation will animate between over time.
    486      * @return An ObjectAnimator object that is set up to animate between the given values.
    487      */
    488     public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property,
    489             float... values) {
    490         ObjectAnimator anim = new ObjectAnimator(target, property);
    491         anim.setFloatValues(values);
    492         return anim;
    493     }
    494 
    495     /**
    496      * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
    497      * using two properties. A <code>Path</code></> animation moves in two dimensions, animating
    498      * coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    499      * coordinates are floats that are set to separate properties, <code>xProperty</code> and
    500      * <code>yProperty</code>.
    501      *
    502      * @param target The object whose properties are to be animated.
    503      * @param xProperty The property for the x coordinate being animated.
    504      * @param yProperty The property for the y coordinate being animated.
    505      * @param path The <code>Path</code> to animate values along.
    506      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    507      */
    508     public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
    509             Property<T, Float> yProperty, Path path) {
    510         PathKeyframes keyframes = KeyframeSet.ofPath(path);
    511         PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty,
    512                 keyframes.createXFloatKeyframes());
    513         PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty,
    514                 keyframes.createYFloatKeyframes());
    515         return ofPropertyValuesHolder(target, x, y);
    516     }
    517 
    518     /**
    519      * Constructs and returns an ObjectAnimator that animates over float values for a multiple
    520      * parameters setter. Only public methods that take only float parameters are supported.
    521      * Each <code>float[]</code> contains a complete set of parameters to the setter method.
    522      * At least two <code>float[]</code> values must be provided, a start and end. More than two
    523      * values imply a starting value, values to animate through along the way, and an ending
    524      * value (these values will be distributed evenly across the duration of the animation).
    525      *
    526      * @param target The object whose property is to be animated. This object may
    527      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    528      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    529      * be the case-sensitive complete name of the public setter method.
    530      * @param propertyName The name of the property being animated or the name of the setter method.
    531      * @param values A set of values that the animation will animate between over time.
    532      * @return An ObjectAnimator object that is set up to animate between the given values.
    533      */
    534     public static ObjectAnimator ofMultiFloat(Object target, String propertyName,
    535             float[][] values) {
    536         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, values);
    537         return ofPropertyValuesHolder(target, pvh);
    538     }
    539 
    540     /**
    541      * Constructs and returns an ObjectAnimator that animates the target using a multi-float setter
    542      * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions,
    543      * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the
    544      * coordinates are float x and y coordinates used in the first and second parameter of the
    545      * setter, respectively.
    546      *
    547      * @param target The object whose property is to be animated. This object may
    548      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    549      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    550      * be the case-sensitive complete name of the public setter method.
    551      * @param propertyName The name of the property being animated or the name of the setter method.
    552      * @param path The <code>Path</code> to animate values along.
    553      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    554      */
    555     public static ObjectAnimator ofMultiFloat(Object target, String propertyName, Path path) {
    556         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, path);
    557         return ofPropertyValuesHolder(target, pvh);
    558     }
    559 
    560     /**
    561      * Constructs and returns an ObjectAnimator that animates over values for a multiple float
    562      * parameters setter. Only public methods that take only float parameters are supported.
    563      * <p>At least two values must be provided, a start and end. More than two
    564      * values imply a starting value, values to animate through along the way, and an ending
    565      * value (these values will be distributed evenly across the duration of the animation).</p>
    566      *
    567      * @param target The object whose property is to be animated. This object may
    568      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    569      * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
    570      * be the case-sensitive complete name of the public setter method.
    571      * @param propertyName The name of the property being animated or the name of the setter method.
    572      * @param converter Converts T objects into float parameters for the multi-value setter.
    573      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    574      * provide the necessary interpolation between the Object values to derive the animated
    575      * value.
    576      * @param values A set of values that the animation will animate between over time.
    577      * @return An ObjectAnimator object that is set up to animate between the given values.
    578      */
    579     @SafeVarargs
    580     public static <T> ObjectAnimator ofMultiFloat(Object target, String propertyName,
    581             TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values) {
    582         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, converter,
    583                 evaluator, values);
    584         return ObjectAnimator.ofPropertyValuesHolder(target, pvh);
    585     }
    586 
    587     /**
    588      * Constructs and returns an ObjectAnimator that animates between Object values. A single
    589      * value implies that that value is the one being animated to, in which case the start value
    590      * will be derived from the property being animated and the target object when {@link #start()}
    591      * is called for the first time. Two values imply starting and ending values. More than two
    592      * values imply a starting value, values to animate through along the way, and an ending value
    593      * (these values will be distributed evenly across the duration of the animation).
    594      *
    595      * <p><strong>Note:</strong> The values are stored as references to the original
    596      * objects, which means that changes to those objects after this method is called will
    597      * affect the values on the animator. If the objects will be mutated externally after
    598      * this method is called, callers should pass a copy of those objects instead.
    599      *
    600      * @param target The object whose property is to be animated. This object should
    601      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    602      * the value of the <code>propertyName</code> parameter.
    603      * @param propertyName The name of the property being animated.
    604      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    605      * provide the necessary interpolation between the Object values to derive the animated
    606      * value.
    607      * @param values A set of values that the animation will animate between over time.
    608      * @return An ObjectAnimator object that is set up to animate between the given values.
    609      */
    610     public static ObjectAnimator ofObject(Object target, String propertyName,
    611             TypeEvaluator evaluator, Object... values) {
    612         ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    613         anim.setObjectValues(values);
    614         anim.setEvaluator(evaluator);
    615         return anim;
    616     }
    617 
    618     /**
    619      * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>.
    620      * A <code>Path</code></> animation moves in two dimensions, animating coordinates
    621      * <code>(x, y)</code> together to follow the line. This variant animates the coordinates
    622      * in a <code>PointF</code> to follow the <code>Path</code>. If the <code>Property</code>
    623      * associated with <code>propertyName</code> uses a type other than <code>PointF</code>,
    624      * <code>converter</code> can be used to change from <code>PointF</code> to the type
    625      * associated with the <code>Property</code>.
    626      *
    627      * @param target The object whose property is to be animated. This object should
    628      * have a public method on it called <code>setName()</code>, where <code>name</code> is
    629      * the value of the <code>propertyName</code> parameter.
    630      * @param propertyName The name of the property being animated.
    631      * @param converter Converts a PointF to the type associated with the setter. May be
    632      *                  null if conversion is unnecessary.
    633      * @param path The <code>Path</code> to animate values along.
    634      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    635      */
    636     @NonNull
    637     public static ObjectAnimator ofObject(Object target, String propertyName,
    638             @Nullable TypeConverter<PointF, ?> converter, Path path) {
    639         PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(propertyName, converter, path);
    640         return ofPropertyValuesHolder(target, pvh);
    641     }
    642 
    643     /**
    644      * Constructs and returns an ObjectAnimator that animates between Object values. A single
    645      * value implies that that value is the one being animated to, in which case the start value
    646      * will be derived from the property being animated and the target object when {@link #start()}
    647      * is called for the first time. Two values imply starting and ending values. More than two
    648      * values imply a starting value, values to animate through along the way, and an ending value
    649      * (these values will be distributed evenly across the duration of the animation).
    650      *
    651      * <p><strong>Note:</strong> The values are stored as references to the original
    652      * objects, which means that changes to those objects after this method is called will
    653      * affect the values on the animator. If the objects will be mutated externally after
    654      * this method is called, callers should pass a copy of those objects instead.
    655      *
    656      * @param target The object whose property is to be animated.
    657      * @param property The property being animated.
    658      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    659      * provide the necessary interpolation between the Object values to derive the animated
    660      * value.
    661      * @param values A set of values that the animation will animate between over time.
    662      * @return An ObjectAnimator object that is set up to animate between the given values.
    663      */
    664     @NonNull
    665     @SafeVarargs
    666     public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
    667             TypeEvaluator<V> evaluator, V... values) {
    668         ObjectAnimator anim = new ObjectAnimator(target, property);
    669         anim.setObjectValues(values);
    670         anim.setEvaluator(evaluator);
    671         return anim;
    672     }
    673 
    674     /**
    675      * Constructs and returns an ObjectAnimator that animates between Object values. A single
    676      * value implies that that value is the one being animated to, in which case the start value
    677      * will be derived from the property being animated and the target object when {@link #start()}
    678      * is called for the first time. Two values imply starting and ending values. More than two
    679      * values imply a starting value, values to animate through along the way, and an ending value
    680      * (these values will be distributed evenly across the duration of the animation).
    681      * This variant supplies a <code>TypeConverter</code> to convert from the animated values to the
    682      * type of the property. If only one value is supplied, the <code>TypeConverter</code> must be a
    683      * {@link android.animation.BidirectionalTypeConverter} to retrieve the current value.
    684      *
    685      * <p><strong>Note:</strong> The values are stored as references to the original
    686      * objects, which means that changes to those objects after this method is called will
    687      * affect the values on the animator. If the objects will be mutated externally after
    688      * this method is called, callers should pass a copy of those objects instead.
    689      *
    690      * @param target The object whose property is to be animated.
    691      * @param property The property being animated.
    692      * @param converter Converts the animated object to the Property type.
    693      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    694      * provide the necessary interpolation between the Object values to derive the animated
    695      * value.
    696      * @param values A set of values that the animation will animate between over time.
    697      * @return An ObjectAnimator object that is set up to animate between the given values.
    698      */
    699     @NonNull
    700     @SafeVarargs
    701     public static <T, V, P> ObjectAnimator ofObject(T target, Property<T, P> property,
    702             TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values) {
    703         PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, evaluator,
    704                 values);
    705         return ofPropertyValuesHolder(target, pvh);
    706     }
    707 
    708     /**
    709      * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>.
    710      * A <code>Path</code></> animation moves in two dimensions, animating coordinates
    711      * <code>(x, y)</code> together to follow the line. This variant animates the coordinates
    712      * in a <code>PointF</code> to follow the <code>Path</code>. If <code>property</code>
    713      * uses a type other than <code>PointF</code>, <code>converter</code> can be used to change
    714      * from <code>PointF</code> to the type associated with the <code>Property</code>.
    715      *
    716      * <p>The PointF passed to <code>converter</code> or <code>property</code>, if
    717      * <code>converter</code> is <code>null</code>, is reused on each animation frame and should
    718      * not be stored by the setter or TypeConverter.</p>
    719      *
    720      * @param target The object whose property is to be animated.
    721      * @param property The property being animated. Should not be null.
    722      * @param converter Converts a PointF to the type associated with the setter. May be
    723      *                  null if conversion is unnecessary.
    724      * @param path The <code>Path</code> to animate values along.
    725      * @return An ObjectAnimator object that is set up to animate along <code>path</code>.
    726      */
    727     @NonNull
    728     public static <T, V> ObjectAnimator ofObject(T target, @NonNull Property<T, V> property,
    729             @Nullable TypeConverter<PointF, V> converter, Path path) {
    730         PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, path);
    731         return ofPropertyValuesHolder(target, pvh);
    732     }
    733 
    734     /**
    735      * Constructs and returns an ObjectAnimator that animates between the sets of values specified
    736      * in <code>PropertyValueHolder</code> objects. This variant should be used when animating
    737      * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows
    738      * you to associate a set of animation values with a property name.
    739      *
    740      * @param target The object whose property is to be animated. Depending on how the
    741      * PropertyValuesObjects were constructed, the target object should either have the {@link
    742      * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the
    743      * PropertyValuesHOlder objects were created with property names) the target object should have
    744      * public methods on it called <code>setName()</code>, where <code>name</code> is the name of
    745      * the property passed in as the <code>propertyName</code> parameter for each of the
    746      * PropertyValuesHolder objects.
    747      * @param values A set of PropertyValuesHolder objects whose values will be animated between
    748      * over time.
    749      * @return An ObjectAnimator object that is set up to animate between the given values.
    750      */
    751     @NonNull
    752     public static ObjectAnimator ofPropertyValuesHolder(Object target,
    753             PropertyValuesHolder... values) {
    754         ObjectAnimator anim = new ObjectAnimator();
    755         anim.setTarget(target);
    756         anim.setValues(values);
    757         return anim;
    758     }
    759 
    760     @Override
    761     public void setIntValues(int... values) {
    762         if (mValues == null || mValues.length == 0) {
    763             // No values yet - this animator is being constructed piecemeal. Init the values with
    764             // whatever the current propertyName is
    765             if (mProperty != null) {
    766                 setValues(PropertyValuesHolder.ofInt(mProperty, values));
    767             } else {
    768                 setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
    769             }
    770         } else {
    771             super.setIntValues(values);
    772         }
    773     }
    774 
    775     @Override
    776     public void setFloatValues(float... values) {
    777         if (mValues == null || mValues.length == 0) {
    778             // No values yet - this animator is being constructed piecemeal. Init the values with
    779             // whatever the current propertyName is
    780             if (mProperty != null) {
    781                 setValues(PropertyValuesHolder.ofFloat(mProperty, values));
    782             } else {
    783                 setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
    784             }
    785         } else {
    786             super.setFloatValues(values);
    787         }
    788     }
    789 
    790     @Override
    791     public void setObjectValues(Object... values) {
    792         if (mValues == null || mValues.length == 0) {
    793             // No values yet - this animator is being constructed piecemeal. Init the values with
    794             // whatever the current propertyName is
    795             if (mProperty != null) {
    796                 setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator) null, values));
    797             } else {
    798                 setValues(PropertyValuesHolder.ofObject(mPropertyName,
    799                         (TypeEvaluator) null, values));
    800             }
    801         } else {
    802             super.setObjectValues(values);
    803         }
    804     }
    805 
    806     /**
    807      * autoCancel controls whether an ObjectAnimator will be canceled automatically
    808      * when any other ObjectAnimator with the same target and properties is started.
    809      * Setting this flag may make it easier to run different animators on the same target
    810      * object without having to keep track of whether there are conflicting animators that
    811      * need to be manually canceled. Canceling animators must have the same exact set of
    812      * target properties, in the same order.
    813      *
    814      * @param cancel Whether future ObjectAnimators with the same target and properties
    815      * as this ObjectAnimator will cause this ObjectAnimator to be canceled.
    816      */
    817     public void setAutoCancel(boolean cancel) {
    818         mAutoCancel = cancel;
    819     }
    820 
    821     private boolean hasSameTargetAndProperties(@Nullable Animator anim) {
    822         if (anim instanceof ObjectAnimator) {
    823             PropertyValuesHolder[] theirValues = ((ObjectAnimator) anim).getValues();
    824             if (((ObjectAnimator) anim).getTarget() == getTarget() &&
    825                     mValues.length == theirValues.length) {
    826                 for (int i = 0; i < mValues.length; ++i) {
    827                     PropertyValuesHolder pvhMine = mValues[i];
    828                     PropertyValuesHolder pvhTheirs = theirValues[i];
    829                     if (pvhMine.getPropertyName() == null ||
    830                             !pvhMine.getPropertyName().equals(pvhTheirs.getPropertyName())) {
    831                         return false;
    832                     }
    833                 }
    834                 return true;
    835             }
    836         }
    837         return false;
    838     }
    839 
    840     @Override
    841     public void start() {
    842         AnimationHandler.getInstance().autoCancelBasedOn(this);
    843         if (DBG) {
    844             Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration());
    845             for (int i = 0; i < mValues.length; ++i) {
    846                 PropertyValuesHolder pvh = mValues[i];
    847                 Log.d(LOG_TAG, "   Values[" + i + "]: " +
    848                     pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " +
    849                     pvh.mKeyframes.getValue(1));
    850             }
    851         }
    852         super.start();
    853     }
    854 
    855     boolean shouldAutoCancel(AnimationHandler.AnimationFrameCallback anim) {
    856         if (anim == null) {
    857             return false;
    858         }
    859 
    860         if (anim instanceof ObjectAnimator) {
    861             ObjectAnimator objAnim = (ObjectAnimator) anim;
    862             if (objAnim.mAutoCancel && hasSameTargetAndProperties(objAnim)) {
    863                 return true;
    864             }
    865         }
    866         return false;
    867     }
    868 
    869     /**
    870      * This function is called immediately before processing the first animation
    871      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
    872      * function is called after that delay ends.
    873      * It takes care of the final initialization steps for the
    874      * animation. This includes setting mEvaluator, if the user has not yet
    875      * set it up, and the setter/getter methods, if the user did not supply
    876      * them.
    877      *
    878      *  <p>Overriders of this method should call the superclass method to cause
    879      *  internal mechanisms to be set up correctly.</p>
    880      */
    881     @CallSuper
    882     @Override
    883     void initAnimation() {
    884         if (!mInitialized) {
    885             // mValueType may change due to setter/getter setup; do this before calling super.init(),
    886             // which uses mValueType to set up the default type evaluator.
    887             final Object target = getTarget();
    888             if (target != null) {
    889                 final int numValues = mValues.length;
    890                 for (int i = 0; i < numValues; ++i) {
    891                     mValues[i].setupSetterAndGetter(target);
    892                 }
    893             }
    894             super.initAnimation();
    895         }
    896     }
    897 
    898     /**
    899      * Sets the length of the animation. The default duration is 300 milliseconds.
    900      *
    901      * @param duration The length of the animation, in milliseconds.
    902      * @return ObjectAnimator The object called with setDuration(). This return
    903      * value makes it easier to compose statements together that construct and then set the
    904      * duration, as in
    905      * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>.
    906      */
    907     @Override
    908     @NonNull
    909     public ObjectAnimator setDuration(long duration) {
    910         super.setDuration(duration);
    911         return this;
    912     }
    913 
    914 
    915     /**
    916      * The target object whose property will be animated by this animation
    917      *
    918      * @return The object being animated
    919      */
    920     @Nullable
    921     public Object getTarget() {
    922         return mTarget == null ? null : mTarget.get();
    923     }
    924 
    925     @Override
    926     public void setTarget(@Nullable Object target) {
    927         final Object oldTarget = getTarget();
    928         if (oldTarget != target) {
    929             if (isStarted()) {
    930                 cancel();
    931             }
    932             mTarget = target == null ? null : new WeakReference<Object>(target);
    933             // New target should cause re-initialization prior to starting
    934             mInitialized = false;
    935         }
    936     }
    937 
    938     @Override
    939     public void setupStartValues() {
    940         initAnimation();
    941 
    942         final Object target = getTarget();
    943         if (target != null) {
    944             final int numValues = mValues.length;
    945             for (int i = 0; i < numValues; ++i) {
    946                 mValues[i].setupStartValue(target);
    947             }
    948         }
    949     }
    950 
    951     @Override
    952     public void setupEndValues() {
    953         initAnimation();
    954 
    955         final Object target = getTarget();
    956         if (target != null) {
    957             final int numValues = mValues.length;
    958             for (int i = 0; i < numValues; ++i) {
    959                 mValues[i].setupEndValue(target);
    960             }
    961         }
    962     }
    963 
    964     /**
    965      * This method is called with the elapsed fraction of the animation during every
    966      * animation frame. This function turns the elapsed fraction into an interpolated fraction
    967      * and then into an animated value (from the evaluator. The function is called mostly during
    968      * animation updates, but it is also called when the <code>end()</code>
    969      * function is called, to set the final value on the property.
    970      *
    971      * <p>Overrides of this method must call the superclass to perform the calculation
    972      * of the animated value.</p>
    973      *
    974      * @param fraction The elapsed fraction of the animation.
    975      */
    976     @CallSuper
    977     @Override
    978     void animateValue(float fraction) {
    979         final Object target = getTarget();
    980         if (mTarget != null && target == null) {
    981             // We lost the target reference, cancel and clean up. Note: we allow null target if the
    982             /// target has never been set.
    983             cancel();
    984             return;
    985         }
    986 
    987         super.animateValue(fraction);
    988         int numValues = mValues.length;
    989         for (int i = 0; i < numValues; ++i) {
    990             mValues[i].setAnimatedValue(target);
    991         }
    992     }
    993 
    994     @Override
    995     boolean isInitialized() {
    996         return mInitialized;
    997     }
    998 
    999     @Override
   1000     public ObjectAnimator clone() {
   1001         final ObjectAnimator anim = (ObjectAnimator) super.clone();
   1002         return anim;
   1003     }
   1004 
   1005     @Override
   1006     @NonNull
   1007     public String toString() {
   1008         String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " +
   1009             getTarget();
   1010         if (mValues != null) {
   1011             for (int i = 0; i < mValues.length; ++i) {
   1012                 returnVal += "\n    " + mValues[i].toString();
   1013             }
   1014         }
   1015         return returnVal;
   1016     }
   1017 }
   1018