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