ObjectAnimator.java revision e2ab7ccd385cdb6517955c719e1d2b49771bedb6
117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase/*
217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Copyright (C) 2010 The Android Open Source Project
317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase *
417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * you may not use this file except in compliance with the License.
617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * You may obtain a copy of the License at
717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase *
817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase *
1017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Unless required by applicable law or agreed to in writing, software
1117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
1217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * See the License for the specific language governing permissions and
1417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * limitations under the License.
1517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */
1617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
1717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haasepackage android.animation;
1817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
1917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haaseimport android.util.Log;
2017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
2117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haaseimport java.lang.reflect.Method;
22e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haaseimport java.util.ArrayList;
2317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
2417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase/**
25a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
2617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * The constructors of this class take parameters to define the target object that will be animated
2717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * as well as the name of the property that will be animated. Appropriate set/get functions
2817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * are then determined internally and the animation will call these functions as necessary to
2917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * animate the property.
306e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase *
316e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @see #setPropertyName(String)
326e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase *
3317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */
342794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haasepublic final class ObjectAnimator extends ValueAnimator {
35e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase    private static final boolean DBG = false;
3617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
3717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    // The target object on which the property exists, set in the constructor
3817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    private Object mTarget;
3917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
4017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    private String mPropertyName;
4117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
4217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
4317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * Sets the name of the property that will be animated. This name is used to derive
4417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * a setter function that will be called to set animated values.
4517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * For example, a property name of <code>foo</code> will result
4617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * in a call to the function <code>setFoo()</code> on the target object. If either
4717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
4817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * also be derived and called.
4917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
506e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * <p>For best performance of the mechanism that calls the setter function determined by the
516e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * name of the property being animated, use <code>float</code> or <code>int</code> typed values,
526e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * and make the setter function for those properties have a <code>void</code> return value. This
536e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * will cause the code to take an optimized path for these constrained circumstances. Other
546e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * property types and return types will work, but will have more overhead in processing
556e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     * the requests due to normal reflection mechanisms.</p>
566e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase     *
5717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * <p>Note that the setter function derived from this property name
5817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * must take the same parameter type as the
5917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
6017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * the setter function will fail.</p>
6117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
62a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * <p>If this ObjectAnimator has been set up to animate several properties together,
63d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * using more than one PropertyValuesHolder objects, then setting the propertyName simply
64d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * sets the propertyName in the first of those PropertyValuesHolder objects.</p>
65d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     *
6617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @param propertyName The name of the property being animated.
6717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
6817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    public void setPropertyName(String propertyName) {
690e0590bf3cb32e73f423c0fe39a180d4b3c4343dChet Haase        // mValues could be null if this is being constructed piecemeal. Just record the
700e0590bf3cb32e73f423c0fe39a180d4b3c4343dChet Haase        // propertyName to be used later when setValues() is called if so.
71d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase        if (mValues != null) {
72602e4d3824bf8b9cb9f817375d195b969712176aChet Haase            PropertyValuesHolder valuesHolder = mValues[0];
73602e4d3824bf8b9cb9f817375d195b969712176aChet Haase            String oldName = valuesHolder.getPropertyName();
74d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase            valuesHolder.setPropertyName(propertyName);
75602e4d3824bf8b9cb9f817375d195b969712176aChet Haase            mValuesMap.remove(oldName);
76602e4d3824bf8b9cb9f817375d195b969712176aChet Haase            mValuesMap.put(propertyName, valuesHolder);
77d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase        }
7817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        mPropertyName = propertyName;
790e0590bf3cb32e73f423c0fe39a180d4b3c4343dChet Haase        // New property/values/target should cause re-initialization prior to starting
800e0590bf3cb32e73f423c0fe39a180d4b3c4343dChet Haase        mInitialized = false;
8117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
8217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
8317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
8417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * Gets the name of the property that will be animated. This name will be used to derive
8517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * a setter function that will be called to set animated values.
8617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * For example, a property name of <code>foo</code> will result
8717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * in a call to the function <code>setFoo()</code> on the target object. If either
8817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
8917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * also be derived and called.
9017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
9117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    public String getPropertyName() {
9217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        return mPropertyName;
9317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
9417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
9517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
9617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * Determine the setter or getter function using the JavaBeans convention of setFoo or
9717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * getFoo for a property named 'foo'. This function figures out what the name of the
9817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * function should be and uses reflection to find the Method with that name on the
9917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * target object.
10017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
10117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @param prefix "set" or "get", depending on whether we need a setter or getter.
10217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @return Method the method associated with mPropertyName.
10317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
104fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase    private Method getPropertyFunction(String prefix, Class valueType) {
10517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        // TODO: faster implementation...
10617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        Method returnVal = null;
10717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        String firstLetter = mPropertyName.substring(0, 1);
10817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        String theRest = mPropertyName.substring(1);
10917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        firstLetter = firstLetter.toUpperCase();
11017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        String setterName = prefix + firstLetter + theRest;
111fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase        Class args[] = null;
112fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase        if (valueType != null) {
113fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase            args = new Class[1];
114fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase            args[0] = valueType;
115fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase        }
11617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        try {
11717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase            returnVal = mTarget.getClass().getMethod(setterName, args);
11817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        } catch (NoSuchMethodException e) {
119a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            Log.e("ObjectAnimator",
120fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase                    "Couldn't find setter/getter for property " + mPropertyName + ": " + e);
12117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        }
12217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        return returnVal;
12317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
12417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
12517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
126a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * Creates a new ObjectAnimator object. This default constructor is primarily for
127d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * use internally; the other constructors which take parameters are more generally
128d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * useful.
129d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
130a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    public ObjectAnimator() {
131d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
132d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
133d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
134d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * A constructor that takes a single property name and set of values. This constructor is
135d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * used in the simple case of animating a single property.
136fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase     *
137fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase     * @param target The object whose property is to be animated. This object should
138d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * have a public method on it called <code>setName()</code>, where <code>name</code> is
139d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * the value of the <code>propertyName</code> parameter.
140d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * @param propertyName The name of the property being animated.
141fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase     */
1422794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private ObjectAnimator(Object target, String propertyName) {
143fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase        mTarget = target;
144d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase        setPropertyName(propertyName);
145fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase    }
146fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase
147fe591563f8529305bd52e1f0640e83b9a93d562fChet Haase    /**
1482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * Constructs and returns an ObjectAnimator that animates between int values. A single
1492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * value implies that that value is the one being animated to. However, this is not typically
1502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * useful in a ValueAnimator object because there is no way for the object to determine the
1512794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * starting value for the animation (unlike ObjectAnimator, which can derive that value
1522794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * from the target object and property being animated). Therefore, there should typically
1532794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * be two or more values.
1542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     *
1552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param target The object whose property is to be animated. This object should
1562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * have a public method on it called <code>setName()</code>, where <code>name</code> is
1572794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * the value of the <code>propertyName</code> parameter.
1582794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param propertyName The name of the property being animated.
1592794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param values A set of values that the animation will animate between over time.
1602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @return A ValueAnimator object that is set up to animate between the given values.
1612794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     */
1622794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
1632794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
1642794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setIntValues(values);
1652794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
1662794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
1672794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
1682794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    /**
1692794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * Constructs and returns an ObjectAnimator that animates between float values. A single
1702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * value implies that that value is the one being animated to. However, this is not typically
1712794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * useful in a ValueAnimator object because there is no way for the object to determine the
1722794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * starting value for the animation (unlike ObjectAnimator, which can derive that value
1732794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * from the target object and property being animated). Therefore, there should typically
1742794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * be two or more values.
1752794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     *
1762794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param target The object whose property is to be animated. This object should
1772794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * have a public method on it called <code>setName()</code>, where <code>name</code> is
1782794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * the value of the <code>propertyName</code> parameter.
1792794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param propertyName The name of the property being animated.
1802794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param values A set of values that the animation will animate between over time.
1812794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @return A ValueAnimator object that is set up to animate between the given values.
1822794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     */
1832794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
1842794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
1852794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setFloatValues(values);
1862794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
1872794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
1882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
1892794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    /**
190d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * A constructor that takes <code>PropertyValueHolder</code> values. This constructor should
191a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * be used when animating several properties at once with the same ObjectAnimator, since
192d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * PropertyValuesHolder allows you to associate a set of animation values with a property
193d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * name.
19417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
19517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @param target The object whose property is to be animated. This object should
196d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * have public methods on it called <code>setName()</code>, where <code>name</code> is
197d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * the name of the property passed in as the <code>propertyName</code> parameter for
198d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * each of the PropertyValuesHolder objects.
1992794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param propertyName The name of the property being animated.
2002794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param evaluator A TypeEvaluator that will be called on each animation frame to
2012794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * provide the ncessry interpolation between the Object values to derive the animated
2022794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * value.
203d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * @param values The PropertyValuesHolder objects which hold each the property name and values
204d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     * to animate that property between.
205d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase     */
2062794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public static ObjectAnimator ofObject(Object target, String propertyName,
2072794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            TypeEvaluator evaluator, Object... values) {
2082794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
2092794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setObjectValues(values);
2102794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setEvaluator(evaluator);
2112794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
2122794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
2132794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
2142794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    /**
2152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * Constructs and returns an ObjectAnimator that animates between the sets of values
2162794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * specifed in <code>PropertyValueHolder</code> objects. This variant should
2172794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * be used when animating several properties at once with the same ObjectAnimator, since
2182794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * PropertyValuesHolder allows you to associate a set of animation values with a property
2192794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * name.
2202794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     *
2212794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param target The object whose property is to be animated. This object should
2222794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * have public methods on it called <code>setName()</code>, where <code>name</code> is
2232794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * the name of the property passed in as the <code>propertyName</code> parameter for
2242794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * each of the PropertyValuesHolder objects.
2252794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param values A set of PropertyValuesHolder objects whose values will be animated
2262794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * between over time.
2272794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @return A ValueAnimator object that is set up to animate between the given values.
2282794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     */
2292794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public static ObjectAnimator ofPropertyValuesHolder(Object target,
2302794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            PropertyValuesHolder... values) {
2312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = new ObjectAnimator();
2322794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.mTarget = target;
2332794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setValues(values);
2342794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
2353dd207a6dbd5d9244dc7fe213d5caa3cddaff0dbChet Haase    }
2363dd207a6dbd5d9244dc7fe213d5caa3cddaff0dbChet Haase
23783d6e8213230fb0805aa019d266842253baeb114Romain Guy    @Override
2382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public void setIntValues(int... values) {
23983d6e8213230fb0805aa019d266842253baeb114Romain Guy        if (mValues == null || mValues.length == 0) {
24083d6e8213230fb0805aa019d266842253baeb114Romain Guy            // No values yet - this animator is being constructed piecemeal. Init the values with
24183d6e8213230fb0805aa019d266842253baeb114Romain Guy            // whatever the current propertyName is
2422794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
24383d6e8213230fb0805aa019d266842253baeb114Romain Guy        } else {
2442794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            super.setIntValues(values);
2452794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        }
2462794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
2472794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
2482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    @Override
2492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public void setFloatValues(float... values) {
2502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        if (mValues == null || mValues.length == 0) {
2512794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            // No values yet - this animator is being constructed piecemeal. Init the values with
2522794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            // whatever the current propertyName is
2532794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
2542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        } else {
2552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            super.setFloatValues(values);
2562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        }
2572794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
2582794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
2592794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    @Override
2602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public void setObjectValues(Object... values) {
2612794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        if (mValues == null || mValues.length == 0) {
2622794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            // No values yet - this animator is being constructed piecemeal. Init the values with
2632794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            // whatever the current propertyName is
2642794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values));
2652794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        } else {
2662794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            super.setObjectValues(values);
26783d6e8213230fb0805aa019d266842253baeb114Romain Guy        }
2680e0590bf3cb32e73f423c0fe39a180d4b3c4343dChet Haase    }
26983d6e8213230fb0805aa019d266842253baeb114Romain Guy
270e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase    @Override
271e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase    public void start() {
272e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase        if (DBG) {
273e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase            Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
274e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase            for (int i = 0; i < mValues.length; ++i) {
275e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase                PropertyValuesHolder pvh = mValues[i];
276e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase                ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
277e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase                Log.d("ObjectAnimator", "   Values[" + i + "]: " +
278e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase                    pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " +
279e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase                    keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue());
280e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase            }
281e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase        }
282e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase        super.start();
283e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase    }
284e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase
2853dd207a6dbd5d9244dc7fe213d5caa3cddaff0dbChet Haase    /**
28617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * This function is called immediately before processing the first animation
28717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * frame of an animation. If there is a nonzero <code>startDelay</code>, the
28817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * function is called after that delay ends.
28917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * It takes care of the final initialization steps for the
29017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * animation. This includes setting mEvaluator, if the user has not yet
29117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * set it up, and the setter/getter methods, if the user did not supply
29217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * them.
29317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
29417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *  <p>Overriders of this method should call the superclass method to cause
29517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *  internal mechanisms to be set up correctly.</p>
29617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
29717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    @Override
29817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    void initAnimation() {
29921cd1389d2ef218b20994b617c57af120841a57fChet Haase        if (!mInitialized) {
30021cd1389d2ef218b20994b617c57af120841a57fChet Haase            // mValueType may change due to setter/getter setup; do this before calling super.init(),
30121cd1389d2ef218b20994b617c57af120841a57fChet Haase            // which uses mValueType to set up the default type evaluator.
30221cd1389d2ef218b20994b617c57af120841a57fChet Haase            int numValues = mValues.length;
30321cd1389d2ef218b20994b617c57af120841a57fChet Haase            for (int i = 0; i < numValues; ++i) {
30421cd1389d2ef218b20994b617c57af120841a57fChet Haase                mValues[i].setupSetterAndGetter(mTarget);
30521cd1389d2ef218b20994b617c57af120841a57fChet Haase            }
30621cd1389d2ef218b20994b617c57af120841a57fChet Haase            super.initAnimation();
30717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        }
30817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
30917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
3102794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    /**
3112794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * Sets the length of the animation. The default duration is 300 milliseconds.
3122794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     *
3132794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @param duration The length of the animation, in milliseconds.
3142794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @return ObjectAnimator The object called with setDuration(). This return
3152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * value makes it easier to compose statements together that construct and then set the
3162794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * duration, as in
3172794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>.
3182794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     */
3192794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    @Override
3202794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public ObjectAnimator setDuration(long duration) {
3212794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        super.setDuration(duration);
3222794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return this;
3232794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    }
3242794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase
32517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
32617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
32717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * The target object whose property will be animated by this animation
32817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
32917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @return The object being animated
33017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
33117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    public Object getTarget() {
33217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        return mTarget;
33317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
33417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase
33517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    /**
336f54a8d7c479485174941c38f151ea7083c658da3Chet Haase     * Sets the target object whose property will be animated by this animation
337f54a8d7c479485174941c38f151ea7083c658da3Chet Haase     *
338f54a8d7c479485174941c38f151ea7083c658da3Chet Haase     * @param target The object being animated
339f54a8d7c479485174941c38f151ea7083c658da3Chet Haase     */
34021cd1389d2ef218b20994b617c57af120841a57fChet Haase    @Override
341f54a8d7c479485174941c38f151ea7083c658da3Chet Haase    public void setTarget(Object target) {
34270d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase        if (mTarget != target) {
34370d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase            mTarget = target;
34470d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase            if (mTarget  != null && target != null && mTarget.getClass() == target.getClass()) {
34570d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase                return;
34670d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase            }
34770d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase            // New target type should cause re-initialization prior to starting
34870d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase            mInitialized = false;
34970d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase        }
350f54a8d7c479485174941c38f151ea7083c658da3Chet Haase    }
351f54a8d7c479485174941c38f151ea7083c658da3Chet Haase
35221cd1389d2ef218b20994b617c57af120841a57fChet Haase    @Override
35321cd1389d2ef218b20994b617c57af120841a57fChet Haase    public void setupStartValues() {
35421cd1389d2ef218b20994b617c57af120841a57fChet Haase        initAnimation();
35521cd1389d2ef218b20994b617c57af120841a57fChet Haase        int numValues = mValues.length;
35621cd1389d2ef218b20994b617c57af120841a57fChet Haase        for (int i = 0; i < numValues; ++i) {
35721cd1389d2ef218b20994b617c57af120841a57fChet Haase            mValues[i].setupStartValue(mTarget);
35821cd1389d2ef218b20994b617c57af120841a57fChet Haase        }
35921cd1389d2ef218b20994b617c57af120841a57fChet Haase    }
36021cd1389d2ef218b20994b617c57af120841a57fChet Haase
36121cd1389d2ef218b20994b617c57af120841a57fChet Haase    @Override
36221cd1389d2ef218b20994b617c57af120841a57fChet Haase    public void setupEndValues() {
36321cd1389d2ef218b20994b617c57af120841a57fChet Haase        initAnimation();
36421cd1389d2ef218b20994b617c57af120841a57fChet Haase        int numValues = mValues.length;
36521cd1389d2ef218b20994b617c57af120841a57fChet Haase        for (int i = 0; i < numValues; ++i) {
36621cd1389d2ef218b20994b617c57af120841a57fChet Haase            mValues[i].setupEndValue(mTarget);
36721cd1389d2ef218b20994b617c57af120841a57fChet Haase        }
36821cd1389d2ef218b20994b617c57af120841a57fChet Haase    }
36921cd1389d2ef218b20994b617c57af120841a57fChet Haase
370f54a8d7c479485174941c38f151ea7083c658da3Chet Haase    /**
37117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * This method is called with the elapsed fraction of the animation during every
37217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * animation frame. This function turns the elapsed fraction into an interpolated fraction
37317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * and then into an animated value (from the evaluator. The function is called mostly during
37417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * animation updates, but it is also called when the <code>end()</code>
37517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * function is called, to set the final value on the property.
37617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
37717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * <p>Overrides of this method must call the superclass to perform the calculation
37817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * of the animated value.</p>
37917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     *
38017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     * @param fraction The elapsed fraction of the animation.
38117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase     */
38217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    @Override
38317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    void animateValue(float fraction) {
38417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        super.animateValue(fraction);
385602e4d3824bf8b9cb9f817375d195b969712176aChet Haase        int numValues = mValues.length;
386602e4d3824bf8b9cb9f817375d195b969712176aChet Haase        for (int i = 0; i < numValues; ++i) {
387602e4d3824bf8b9cb9f817375d195b969712176aChet Haase            mValues[i].setAnimatedValue(mTarget);
38817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase        }
38917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase    }
39049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase
39149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase    @Override
392a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    public ObjectAnimator clone() {
393a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        final ObjectAnimator anim = (ObjectAnimator) super.clone();
39449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase        return anim;
39549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase    }
39617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase}
397