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