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