1d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase/* 2d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Copyright (C) 2010 The Android Open Source Project 3d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 4d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * you may not use this file except in compliance with the License. 6d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * You may obtain a copy of the License at 7d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 8d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 9d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 10d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Unless required by applicable law or agreed to in writing, software 11d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * See the License for the specific language governing permissions and 14d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * limitations under the License. 15d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 16d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 17d953d08e9299072130d9f4411cbcf6678bbce822Chet Haasepackage android.animation; 18d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 19c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mountimport android.graphics.Path; 20c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mountimport android.graphics.PointF; 21b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.FloatProperty; 22b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.IntProperty; 23d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport android.util.Log; 24766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.PathParser; 25b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.Property; 26d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 27d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.lang.reflect.InvocationTargetException; 28d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.lang.reflect.Method; 29d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.util.HashMap; 30d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyarimport java.util.List; 31d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 32d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase/** 3321cd1389d2ef218b20994b617c57af120841a57fChet Haase * This class holds information about a property and the values that that property 3421cd1389d2ef218b20994b617c57af120841a57fChet Haase * should take on during an animation. PropertyValuesHolder objects can be used to create 35a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations with ValueAnimator or ObjectAnimator that operate on several different properties 3621cd1389d2ef218b20994b617c57af120841a57fChet Haase * in parallel. 37d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haasepublic class PropertyValuesHolder implements Cloneable { 39d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 40d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 41d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The name of the property associated with the values. This need not be a real property, 42a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * unless this object is being used with ObjectAnimator. But this is the name by which 43a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator. 44d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 456e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String mPropertyName; 46d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 47d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 48b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @hide 49b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 50b39f051631250c49936a475d0e64584afb7f1b93Chet Haase protected Property mProperty; 51b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 52b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 53a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * The setter function, if needed. ObjectAnimator hands off this functionality to 54d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * PropertyValuesHolder, since it holds all of the per-property information. This 5537f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase * property is automatically 56a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. 57d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Method mSetter = null; 59d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 60d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 61a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * The getter function, if needed. ObjectAnimator hands off this functionality to 62d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * PropertyValuesHolder, since it holds all of the per-property information. This 6337f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase * property is automatically 64a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. 65d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The getter is only derived and used if one of the values is null. 66d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 67d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method mGetter = null; 68d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 69d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 70d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The type of values supplied. This information is used both in deriving the setter/getter 71d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * functions and in deriving the type of TypeEvaluator. 72d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 737c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Class mValueType; 74d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 75d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 76d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The set of keyframes (time/value pairs) that define this animation. 77d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 78984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes mKeyframes = null; 79d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 80d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 81b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // type evaluators for the primitive types handled by this implementation 82d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); 83d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); 84d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 85d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // We try several different types when searching for appropriate setter/getter functions. 86d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // The caller may have supplied values in a type that does not match the setter/getter 87d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // functions (such as the integers 0 and 1 to represent floating point values for alpha). 88d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Also, the use of generics in constructors means that we end up with the Object versions 89d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // of primitive types (Float vs. float). But most likely, the setter/getter functions 90d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // will take primitive types instead. 91d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // So we supply an ordered array of other types to try before giving up. 92d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class, 93d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Double.class, Integer.class}; 94d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class, 95d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Float.class, Double.class}; 96d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] DOUBLE_VARIANTS = {double.class, Double.class, float.class, int.class, 97d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Float.class, Integer.class}; 98d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 99d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // These maps hold all property entries for a particular class. This map 100d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // is used to speed up property/setter/getter lookups for a given class/property 101d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // combination. No need to use reflection on the combination more than once. 102d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final HashMap<Class, HashMap<String, Method>> sSetterPropertyMap = 103d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase new HashMap<Class, HashMap<String, Method>>(); 104d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final HashMap<Class, HashMap<String, Method>> sGetterPropertyMap = 105d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase new HashMap<Class, HashMap<String, Method>>(); 106d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 107d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Used to pass single value to varargs parameter in setter invocation 1086e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase final Object[] mTmpValueArray = new Object[1]; 109d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 110d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 111d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The type evaluator used to calculate the animated values. This evaluator is determined 112d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * automatically based on the type of the start/end objects passed into the constructor, 113b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase * but the system only knows about the primitive types int and float. Any other 114d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * type will need to set the evaluator to a custom evaluator for that type. 115d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 116d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private TypeEvaluator mEvaluator; 117d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 118d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 119d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The value most recently calculated by calculateValue(). This is set during 120a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * that function and might be retrieved later either by ValueAnimator.animatedValue() or 121a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * by the property-setting logic in ObjectAnimator.animatedValue(). 122d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 123d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Object mAnimatedValue; 124d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 125d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 12616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * Converts from the source Object type to the setter Object type. 12716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount */ 12816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount private TypeConverter mConverter; 12916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount 13016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount /** 1312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Internal utility constructor, used by the factory methods to set the property name. 1322794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property for this holder. 133d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 1342794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase private PropertyValuesHolder(String propertyName) { 1352794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mPropertyName = propertyName; 1362794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 1372794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 1382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 139b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Internal utility constructor, used by the factory methods to set the property. 140b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property for this holder. 141b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 142b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private PropertyValuesHolder(Property property) { 143b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = property; 144b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property != null) { 145b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mPropertyName = property.getName(); 146b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 147b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 148b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 149b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 1502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 1512794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of int values. 1522794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 1532794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 1542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 1552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 1562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofInt(String propertyName, int... values) { 157b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new IntPropertyValuesHolder(propertyName, values); 158b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 159b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 160b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 161b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 162b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of int values. 163b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 164b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 165b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 166b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 167b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values) { 168b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new IntPropertyValuesHolder(property, values); 1692794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 1702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 1712794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 1722794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 1734eed52944c0fcb3afa7369aba60fb5c655580286George Mount * set of <code>int[]</code> values. At least two <code>int[]</code> values must be supplied, 1744eed52944c0fcb3afa7369aba60fb5c655580286George Mount * a start and end value. If more values are supplied, the values will be animated from the 1754eed52944c0fcb3afa7369aba60fb5c655580286George Mount * start, through all intermediate values to the end value. When used with ObjectAnimator, 1764eed52944c0fcb3afa7369aba60fb5c655580286George Mount * the elements of the array represent the parameters of the setter function. 1774eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 178c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param propertyName The name of the property being animated. Can also be the 179c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * case-sensitive name of the entire setter method. Should not be null. 1804eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values that the property will animate between. 1814eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 1824eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see IntArrayEvaluator#IntArrayEvaluator(int[]) 1834eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see ObjectAnimator#ofMultiInt(Object, String, TypeConverter, TypeEvaluator, Object[]) 1844eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 1854eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static PropertyValuesHolder ofMultiInt(String propertyName, int[][] values) { 1864eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (values.length < 2) { 1874eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("At least 2 values must be supplied"); 1884eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1894eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParameters = 0; 1904eed52944c0fcb3afa7369aba60fb5c655580286George Mount for (int i = 0; i < values.length; i++) { 1914eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (values[i] == null) { 1924eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("values must not be null"); 1934eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1944eed52944c0fcb3afa7369aba60fb5c655580286George Mount int length = values[i].length; 1954eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (i == 0) { 1964eed52944c0fcb3afa7369aba60fb5c655580286George Mount numParameters = length; 1974eed52944c0fcb3afa7369aba60fb5c655580286George Mount } else if (length != numParameters) { 1984eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("Values must all have the same length"); 1994eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 2004eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 2014eed52944c0fcb3afa7369aba60fb5c655580286George Mount IntArrayEvaluator evaluator = new IntArrayEvaluator(new int[numParameters]); 2024eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiIntValuesHolder(propertyName, null, evaluator, (Object[]) values); 2034eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 2044eed52944c0fcb3afa7369aba60fb5c655580286George Mount 2054eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 206c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Constructs and returns a PropertyValuesHolder with a given property name to use 207c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * as a multi-int setter. The values are animated along the path, with the first 208c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * parameter of the setter set to the x coordinate and the second set to the y coordinate. 209c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * 210c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param propertyName The name of the property being animated. Can also be the 211c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * case-sensitive name of the entire setter method. Should not be null. 212c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * The setter must take exactly two <code>int</code> parameters. 213c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param path The Path along which the values should be animated. 214c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 215c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) 216c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 217c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public static PropertyValuesHolder ofMultiInt(String propertyName, Path path) { 218984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes keyframes = KeyframeSet.ofPath(path); 219c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount PointFToIntArray converter = new PointFToIntArray(); 220984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new MultiIntValuesHolder(propertyName, converter, null, keyframes); 221c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 222c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 223c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 2244eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder with a given property and 2254eed52944c0fcb3afa7369aba60fb5c655580286George Mount * set of Object values for use with ObjectAnimator multi-value setters. The Object 2264eed52944c0fcb3afa7369aba60fb5c655580286George Mount * values are converted to <code>int[]</code> using the converter. 2274eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 2284eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param propertyName The property being animated or complete name of the setter. 2294eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Should not be null. 2304eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param converter Used to convert the animated value to setter parameters. 2314eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param evaluator A TypeEvaluator that will be called on each animation frame to 2324eed52944c0fcb3afa7369aba60fb5c655580286George Mount * provide the necessary interpolation between the Object values to derive the animated 2334eed52944c0fcb3afa7369aba60fb5c655580286George Mount * value. 2344eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values that the property will animate between. 2354eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 2364eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see ObjectAnimator#ofMultiInt(Object, String, TypeConverter, TypeEvaluator, Object[]) 2374eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) 2384eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 239d98f4ba86c02714d94ec3b6f35345cb0b04f7778George Mount @SafeVarargs 2404eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static <V> PropertyValuesHolder ofMultiInt(String propertyName, 2414eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeConverter<V, int[]> converter, TypeEvaluator<V> evaluator, V... values) { 2424eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiIntValuesHolder(propertyName, converter, evaluator, values); 2434eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 2444eed52944c0fcb3afa7369aba60fb5c655580286George Mount 2454eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 2464eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder object with the specified property name or 2474eed52944c0fcb3afa7369aba60fb5c655580286George Mount * setter name for use in a multi-int setter function using ObjectAnimator. The values can be 2484eed52944c0fcb3afa7369aba60fb5c655580286George Mount * of any type, but the type should be consistent so that the supplied 2494eed52944c0fcb3afa7369aba60fb5c655580286George Mount * {@link android.animation.TypeEvaluator} can be used to to evaluate the animated value. The 2504eed52944c0fcb3afa7369aba60fb5c655580286George Mount * <code>converter</code> converts the values to parameters in the setter function. 2514eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 2524eed52944c0fcb3afa7369aba60fb5c655580286George Mount * <p>At least two values must be supplied, a start and an end value.</p> 2534eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 2544eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param propertyName The name of the property to associate with the set of values. This 2554eed52944c0fcb3afa7369aba60fb5c655580286George Mount * may also be the complete name of a setter function. 2564eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param converter Converts <code>values</code> into int parameters for the setter. 2574eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Can be null if the Keyframes have int[] values. 2584eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param evaluator Used to interpolate between values. 2594eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values at specific fractional times to evaluate between 2604eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return A PropertyValuesHolder for a multi-int parameter setter. 2614eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 2624eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static <T> PropertyValuesHolder ofMultiInt(String propertyName, 2634eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, Keyframe... values) { 2644eed52944c0fcb3afa7369aba60fb5c655580286George Mount KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 2654eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiIntValuesHolder(propertyName, converter, evaluator, keyframeSet); 2664eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 2674eed52944c0fcb3afa7369aba60fb5c655580286George Mount 2684eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 2694eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder with a given property name and 2702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of float values. 2712794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 2722794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 2732794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 2742794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 2752794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofFloat(String propertyName, float... values) { 276b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new FloatPropertyValuesHolder(propertyName, values); 277b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 278b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 279b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 280b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 281b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of float values. 282b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 283b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 284b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 285b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 286b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) { 287b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new FloatPropertyValuesHolder(property, values); 2882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 2892794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 2902794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 2912794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 2924eed52944c0fcb3afa7369aba60fb5c655580286George Mount * set of <code>float[]</code> values. At least two <code>float[]</code> values must be supplied, 2934eed52944c0fcb3afa7369aba60fb5c655580286George Mount * a start and end value. If more values are supplied, the values will be animated from the 2944eed52944c0fcb3afa7369aba60fb5c655580286George Mount * start, through all intermediate values to the end value. When used with ObjectAnimator, 2954eed52944c0fcb3afa7369aba60fb5c655580286George Mount * the elements of the array represent the parameters of the setter function. 2964eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 297c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param propertyName The name of the property being animated. Can also be the 298c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * case-sensitive name of the entire setter method. Should not be null. 2994eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values that the property will animate between. 3004eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 3014eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see FloatArrayEvaluator#FloatArrayEvaluator(float[]) 3024eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see ObjectAnimator#ofMultiFloat(Object, String, TypeConverter, TypeEvaluator, Object[]) 3034eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 3044eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static PropertyValuesHolder ofMultiFloat(String propertyName, float[][] values) { 3054eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (values.length < 2) { 3064eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("At least 2 values must be supplied"); 3074eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3084eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParameters = 0; 3094eed52944c0fcb3afa7369aba60fb5c655580286George Mount for (int i = 0; i < values.length; i++) { 3104eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (values[i] == null) { 3114eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("values must not be null"); 3124eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3134eed52944c0fcb3afa7369aba60fb5c655580286George Mount int length = values[i].length; 3144eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (i == 0) { 3154eed52944c0fcb3afa7369aba60fb5c655580286George Mount numParameters = length; 3164eed52944c0fcb3afa7369aba60fb5c655580286George Mount } else if (length != numParameters) { 3174eed52944c0fcb3afa7369aba60fb5c655580286George Mount throw new IllegalArgumentException("Values must all have the same length"); 3184eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3194eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3204eed52944c0fcb3afa7369aba60fb5c655580286George Mount FloatArrayEvaluator evaluator = new FloatArrayEvaluator(new float[numParameters]); 3214eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiFloatValuesHolder(propertyName, null, evaluator, (Object[]) values); 3224eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3234eed52944c0fcb3afa7369aba60fb5c655580286George Mount 3244eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 325c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Constructs and returns a PropertyValuesHolder with a given property name to use 326c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * as a multi-float setter. The values are animated along the path, with the first 327c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * parameter of the setter set to the x coordinate and the second set to the y coordinate. 328c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * 329c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param propertyName The name of the property being animated. Can also be the 330c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * case-sensitive name of the entire setter method. Should not be null. 331c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * The setter must take exactly two <code>float</code> parameters. 332c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param path The Path along which the values should be animated. 333c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 334c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) 335c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 336c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public static PropertyValuesHolder ofMultiFloat(String propertyName, Path path) { 337984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes keyframes = KeyframeSet.ofPath(path); 338c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount PointFToFloatArray converter = new PointFToFloatArray(); 339984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new MultiFloatValuesHolder(propertyName, converter, null, keyframes); 340c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 341c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 342c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 3434eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder with a given property and 3444eed52944c0fcb3afa7369aba60fb5c655580286George Mount * set of Object values for use with ObjectAnimator multi-value setters. The Object 3454eed52944c0fcb3afa7369aba60fb5c655580286George Mount * values are converted to <code>float[]</code> using the converter. 3464eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 3474eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param propertyName The property being animated or complete name of the setter. 3484eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Should not be null. 3494eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param converter Used to convert the animated value to setter parameters. 3504eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param evaluator A TypeEvaluator that will be called on each animation frame to 3514eed52944c0fcb3afa7369aba60fb5c655580286George Mount * provide the necessary interpolation between the Object values to derive the animated 3524eed52944c0fcb3afa7369aba60fb5c655580286George Mount * value. 3534eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values that the property will animate between. 3544eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 3554eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @see ObjectAnimator#ofMultiFloat(Object, String, TypeConverter, TypeEvaluator, Object[]) 3564eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 357d98f4ba86c02714d94ec3b6f35345cb0b04f7778George Mount @SafeVarargs 3584eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static <V> PropertyValuesHolder ofMultiFloat(String propertyName, 3594eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeConverter<V, float[]> converter, TypeEvaluator<V> evaluator, V... values) { 3604eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiFloatValuesHolder(propertyName, converter, evaluator, values); 3614eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3624eed52944c0fcb3afa7369aba60fb5c655580286George Mount 3634eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 3644eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder object with the specified property name or 3654eed52944c0fcb3afa7369aba60fb5c655580286George Mount * setter name for use in a multi-float setter function using ObjectAnimator. The values can be 3664eed52944c0fcb3afa7369aba60fb5c655580286George Mount * of any type, but the type should be consistent so that the supplied 3674eed52944c0fcb3afa7369aba60fb5c655580286George Mount * {@link android.animation.TypeEvaluator} can be used to to evaluate the animated value. The 3684eed52944c0fcb3afa7369aba60fb5c655580286George Mount * <code>converter</code> converts the values to parameters in the setter function. 3694eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 3704eed52944c0fcb3afa7369aba60fb5c655580286George Mount * <p>At least two values must be supplied, a start and an end value.</p> 3714eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 3724eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param propertyName The name of the property to associate with the set of values. This 3734eed52944c0fcb3afa7369aba60fb5c655580286George Mount * may also be the complete name of a setter function. 3744eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param converter Converts <code>values</code> into float parameters for the setter. 3754eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Can be null if the Keyframes have float[] values. 3764eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param evaluator Used to interpolate between values. 3774eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param values The values at specific fractional times to evaluate between 3784eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @return A PropertyValuesHolder for a multi-float parameter setter. 3794eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 3804eed52944c0fcb3afa7369aba60fb5c655580286George Mount public static <T> PropertyValuesHolder ofMultiFloat(String propertyName, 3814eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, Keyframe... values) { 3824eed52944c0fcb3afa7369aba60fb5c655580286George Mount KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 3834eed52944c0fcb3afa7369aba60fb5c655580286George Mount return new MultiFloatValuesHolder(propertyName, converter, evaluator, keyframeSet); 3844eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 3854eed52944c0fcb3afa7369aba60fb5c655580286George Mount 3864eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 3874eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Constructs and returns a PropertyValuesHolder with a given property name and 3882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of Object values. This variant also takes a TypeEvaluator because the system 389b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * cannot automatically interpolate between objects of unknown type. 3902794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 391fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * <p><strong>Note:</strong> The Object values are stored as references to the original 392fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * objects, which means that changes to those objects after this method is called will 393fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * affect the values on the PropertyValuesHolder. If the objects will be mutated externally 394fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * after this method is called, callers should pass a copy of those objects instead. 395fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * 3962794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 3972794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param evaluator A TypeEvaluator that will be called on each animation frame to 398b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * provide the necessary interpolation between the Object values to derive the animated 3992794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * value. 4002794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 4012794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 4022794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 4032794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, 4042794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase Object... values) { 4052794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); 4062794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase pvh.setObjectValues(values); 4072794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase pvh.setEvaluator(evaluator); 4082794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase return pvh; 409d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 410d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 411d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 412c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Constructs and returns a PropertyValuesHolder with a given property name and 413c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * a Path along which the values should be animated. This variant supports a 414c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * <code>TypeConverter</code> to convert from <code>PointF</code> to the target 415c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * type. 416c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * 417984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <p>The PointF passed to <code>converter</code> or <code>property</code>, if 418984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <code>converter</code> is <code>null</code>, is reused on each animation frame and should 419984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * not be stored by the setter or TypeConverter.</p> 420984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * 421c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param propertyName The name of the property being animated. 422c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param converter Converts a PointF to the type associated with the setter. May be 423c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * null if conversion is unnecessary. 424c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param path The Path along which the values should be animated. 425c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 426c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 427c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public static PropertyValuesHolder ofObject(String propertyName, 428c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount TypeConverter<PointF, ?> converter, Path path) { 429984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); 430984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mKeyframes = KeyframeSet.ofPath(path); 431984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mValueType = PointF.class; 432c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount pvh.setConverter(converter); 433c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return pvh; 434c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 435c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 436c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 437b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 438b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of Object values. This variant also takes a TypeEvaluator because the system 439b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * cannot automatically interpolate between objects of unknown type. 440b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 441fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * <p><strong>Note:</strong> The Object values are stored as references to the original 442fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * objects, which means that changes to those objects after this method is called will 443fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * affect the values on the PropertyValuesHolder. If the objects will be mutated externally 444fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * after this method is called, callers should pass a copy of those objects instead. 445fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * 446b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 447b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param evaluator A TypeEvaluator that will be called on each animation frame to 448b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * provide the necessary interpolation between the Object values to derive the animated 449b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * value. 450b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 451b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 452b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 453d98f4ba86c02714d94ec3b6f35345cb0b04f7778George Mount @SafeVarargs 454b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static <V> PropertyValuesHolder ofObject(Property property, 455b39f051631250c49936a475d0e64584afb7f1b93Chet Haase TypeEvaluator<V> evaluator, V... values) { 456b39f051631250c49936a475d0e64584afb7f1b93Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(property); 457b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.setObjectValues(values); 458b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.setEvaluator(evaluator); 459b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return pvh; 460b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 461b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 462b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 46316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * Constructs and returns a PropertyValuesHolder with a given property and 46416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * set of Object values. This variant also takes a TypeEvaluator because the system 46516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * cannot automatically interpolate between objects of unknown type. This variant also 46616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * takes a <code>TypeConverter</code> to convert from animated values to the type 46716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * of the property. If only one value is supplied, the <code>TypeConverter</code> 46842516d19db936b10874c27e16eeacda041af01f9George Mount * must be a {@link android.animation.BidirectionalTypeConverter} to retrieve the current 46916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * value. 47016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * 471fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * <p><strong>Note:</strong> The Object values are stored as references to the original 472fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * objects, which means that changes to those objects after this method is called will 473fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * affect the values on the PropertyValuesHolder. If the objects will be mutated externally 474fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * after this method is called, callers should pass a copy of those objects instead. 475fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * 47616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @param property The property being animated. Should not be null. 47716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @param converter Converts the animated object to the Property type. 47816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @param evaluator A TypeEvaluator that will be called on each animation frame to 47916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * provide the necessary interpolation between the Object values to derive the animated 48016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * value. 48116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @param values The values that the property will animate between. 48216d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 48316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @see #setConverter(TypeConverter) 48416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @see TypeConverter 48516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount */ 486d98f4ba86c02714d94ec3b6f35345cb0b04f7778George Mount @SafeVarargs 48716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount public static <T, V> PropertyValuesHolder ofObject(Property<?, V> property, 48816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount TypeConverter<T, V> converter, TypeEvaluator<T> evaluator, T... values) { 48916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount PropertyValuesHolder pvh = new PropertyValuesHolder(property); 49016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount pvh.setConverter(converter); 49116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount pvh.setObjectValues(values); 49216d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount pvh.setEvaluator(evaluator); 49316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount return pvh; 49416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 49516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount 49616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount /** 497c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Constructs and returns a PropertyValuesHolder with a given property and 498c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * a Path along which the values should be animated. This variant supports a 499c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * <code>TypeConverter</code> to convert from <code>PointF</code> to the target 500c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * type. 501c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * 502984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <p>The PointF passed to <code>converter</code> or <code>property</code>, if 503984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <code>converter</code> is <code>null</code>, is reused on each animation frame and should 504984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * not be stored by the setter or TypeConverter.</p> 505984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * 506c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param property The property being animated. Should not be null. 507c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param converter Converts a PointF to the type associated with the setter. May be 508c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * null if conversion is unnecessary. 509c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @param path The Path along which the values should be animated. 510c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 511c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 512c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public static <V> PropertyValuesHolder ofObject(Property<?, V> property, 513c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount TypeConverter<PointF, V> converter, Path path) { 514984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PropertyValuesHolder pvh = new PropertyValuesHolder(property); 515984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mKeyframes = KeyframeSet.ofPath(path); 516984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mValueType = PointF.class; 517c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount pvh.setConverter(converter); 518c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return pvh; 519c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 520c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 521c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 5222794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder object with the specified property name and set 5232794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * of values. These values can be of any type, but the type should be consistent so that 524d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * an appropriate {@link android.animation.TypeEvaluator} can be found that matches 525d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * the common type. 526d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <p>If there is only one value, it is assumed to be the end value of an animation, 527d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and an initial value will be derived, if possible, by calling a getter function 528d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 529d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 530d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * if the PropertyValuesHolder object is used in conjunction 5311a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 5321a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 533d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * no way of determining what the value should be. 534d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyName The name of the property associated with this set of values. This 535a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * can be the actual property name to be used when using a ObjectAnimator object, or 536d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * just a name used to get animated values, such as if this object is used with an 537a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * ValueAnimator object. 538d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param values The set of values to animate between. 539d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 5402794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { 5417c608f25d494c8a0a671e7373efbb47ca635367eChet Haase KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 542984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return ofKeyframes(propertyName, keyframeSet); 543d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 544d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 545d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 546b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder object with the specified property and set 547b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * of values. These values can be of any type, but the type should be consistent so that 548b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * an appropriate {@link android.animation.TypeEvaluator} can be found that matches 549b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * the common type. 550b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * <p>If there is only one value, it is assumed to be the end value of an animation, 551b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * and an initial value will be derived, if possible, by calling the property's 552b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * {@link android.util.Property#get(Object)} function. 553b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Also, if any value is null, the value will be filled in when the animation 554b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 555b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * if the PropertyValuesHolder object is used in conjunction with 556b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has 557b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * no way of determining what the value should be. 558b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property associated with this set of values. Should not be null. 559b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The set of values to animate between. 560b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 561b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { 562b39f051631250c49936a475d0e64584afb7f1b93Chet Haase KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 563984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return ofKeyframes(property, keyframeSet); 564984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 565984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 566984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount static PropertyValuesHolder ofKeyframes(String propertyName, Keyframes keyframes) { 567984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (keyframes instanceof Keyframes.IntKeyframes) { 568984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new IntPropertyValuesHolder(propertyName, (Keyframes.IntKeyframes) keyframes); 569984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else if (keyframes instanceof Keyframes.FloatKeyframes) { 570984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new FloatPropertyValuesHolder(propertyName, 571984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount (Keyframes.FloatKeyframes) keyframes); 572984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else { 573984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); 574984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mKeyframes = keyframes; 575984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mValueType = keyframes.getType(); 576984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pvh; 577b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 578984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 579984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 580984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount static PropertyValuesHolder ofKeyframes(Property property, Keyframes keyframes) { 581984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (keyframes instanceof Keyframes.IntKeyframes) { 582984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new IntPropertyValuesHolder(property, (Keyframes.IntKeyframes) keyframes); 583984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else if (keyframes instanceof Keyframes.FloatKeyframes) { 584984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new FloatPropertyValuesHolder(property, (Keyframes.FloatKeyframes) keyframes); 585984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else { 586b39f051631250c49936a475d0e64584afb7f1b93Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(property); 587984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mKeyframes = keyframes; 588984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount pvh.mValueType = keyframes.getType(); 589b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return pvh; 590b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 591b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 592b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 593b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 5942794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of ints. 595d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 596d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and an initial value will be derived, if possible, by calling a getter function 597d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 598d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 599d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * if the PropertyValuesHolder object is used in conjunction 6001a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 6011a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 602d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * no way of determining what the value should be. 6032794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 6042794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 6052794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 6062794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setIntValues(int... values) { 6072794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = int.class; 608984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = KeyframeSet.ofInt(values); 6092794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 6102794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 6112794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 6122794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of floats. 6132794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 6142794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * and an initial value will be derived, if possible, by calling a getter function 6152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 6162794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 6172794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * if the PropertyValuesHolder object is used in conjunction 6181a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 6191a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 6202794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * no way of determining what the value should be. 6212794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 6222794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 6232794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 6242794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setFloatValues(float... values) { 6252794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = float.class; 626984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = KeyframeSet.ofFloat(values); 6272794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 6282794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 6292794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 6302794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of Keyframes. 6312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 6322794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 633d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 6342794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setKeyframes(Keyframe... values) { 635d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase int numKeyframes = values.length; 636d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; 6372794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = ((Keyframe)values[0]).getType(); 6382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase for (int i = 0; i < numKeyframes; ++i) { 6392794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase keyframes[i] = (Keyframe)values[i]; 640d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 641984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = new KeyframeSet(keyframes); 642d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 643d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 6442794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 6452794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of Objects. 6462794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 6472794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * and an initial value will be derived, if possible, by calling a getter function 6482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 6492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 6502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * if the PropertyValuesHolder object is used in conjunction 6511a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 6521a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 6532794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * no way of determining what the value should be. 654fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * 655fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * <p><strong>Note:</strong> The Object values are stored as references to the original 656fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * objects, which means that changes to those objects after this method is called will 657fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * affect the values on the PropertyValuesHolder. If the objects will be mutated externally 658fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * after this method is called, callers should pass a copy of those objects instead. 659fa21bdfd5a8a5da3ec0530f7cc884994f92dc597Chet Haase * 6602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 6612794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 6622794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setObjectValues(Object... values) { 6632794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = values[0].getClass(); 664984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = KeyframeSet.ofObject(values); 6654ae3e6af08919e31174e049d2509e73a9bebb2b3Chet Haase if (mEvaluator != null) { 666984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes.setEvaluator(mEvaluator); 6674ae3e6af08919e31174e049d2509e73a9bebb2b3Chet Haase } 6682794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 669d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 670d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 67116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * Sets the converter to convert from the values type to the setter's parameter type. 67242516d19db936b10874c27e16eeacda041af01f9George Mount * If only one value is supplied, <var>converter</var> must be a 67342516d19db936b10874c27e16eeacda041af01f9George Mount * {@link android.animation.BidirectionalTypeConverter}. 67416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount * @param converter The converter to use to convert values. 67516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount */ 67616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount public void setConverter(TypeConverter converter) { 67716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount mConverter = converter; 67816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 67916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount 68016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount /** 681d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Determine the setter or getter function using the JavaBeans convention of setFoo or 682d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * getFoo for a property named 'foo'. This function figures out what the name of the 683d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * function should be and uses reflection to find the Method with that name on the 684d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * target object. 685d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 686d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The class to search for the method 687d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param prefix "set" or "get", depending on whether we need a setter or getter. 688d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param valueType The type of the parameter (in the case of a setter). This type 689d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * is derived from the values set on this PropertyValuesHolder. This type is used as 690d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a first guess at the parameter type, but we check for methods with several different 691d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * types to avoid problems with slight mis-matches between supplied values and actual 692d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * value types used on the setter. 693d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return Method the method associated with mPropertyName. 694d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 695d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) { 696d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // TODO: faster implementation... 697d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Method returnVal = null; 6986e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName(prefix, mPropertyName); 699d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Class args[] = null; 700d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (valueType == null) { 701d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 702d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase returnVal = targetClass.getMethod(methodName, args); 703d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (NoSuchMethodException e) { 704db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Swallow the error, log it later 705d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 706d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else { 707d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase args = new Class[1]; 708d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Class typeVariants[]; 70916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount if (valueType.equals(Float.class)) { 710d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = FLOAT_VARIANTS; 71116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } else if (valueType.equals(Integer.class)) { 712d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = INTEGER_VARIANTS; 71316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } else if (valueType.equals(Double.class)) { 714d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = DOUBLE_VARIANTS; 715d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else { 716d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = new Class[1]; 71716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount typeVariants[0] = valueType; 718d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 719d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase for (Class typeVariant : typeVariants) { 720d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase args[0] = typeVariant; 721d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 722d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase returnVal = targetClass.getMethod(methodName, args); 72316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount if (mConverter == null) { 72416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount // change the value type to suit 72516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount mValueType = typeVariant; 72616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 727d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return returnVal; 728d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (NoSuchMethodException e) { 729d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Swallow the error and keep trying other variants 730d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 731d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 732602e4d3824bf8b9cb9f817375d195b969712176aChet Haase // If we got here, then no appropriate function was found 733db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 734db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase 735db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (returnVal == null) { 736db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase Log.w("PropertyValuesHolder", "Method " + 73716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount getMethodName(prefix, mPropertyName) + "() with type " + valueType + 738db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase " not found on target class " + targetClass); 739d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 740602e4d3824bf8b9cb9f817375d195b969712176aChet Haase 741d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return returnVal; 742d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 743d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 744d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 745d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 746d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Returns the setter or getter requested. This utility function checks whether the 747d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * requested method exists in the propertyMapMap cache. If not, it calls another 748d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * utility function to request the Method from the targetClass directly. 749d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The Class on which the requested method should exist. 750d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyMapMap The cache of setters/getters derived so far. 751d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param prefix "set" or "get", for the setter or getter. 752d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param valueType The type of parameter passed into the method (null for getter). 753d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return Method the method associated with mPropertyName. 754d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 755d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method setupSetterOrGetter(Class targetClass, 756d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase HashMap<Class, HashMap<String, Method>> propertyMapMap, 757d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase String prefix, Class valueType) { 758d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Method setterOrGetter = null; 759691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount synchronized(propertyMapMap) { 760d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Have to lock property map prior to reading it, to guard against 761d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // another thread putting something in there after we've checked it 762d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // but before we've added an entry to it 763d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass); 764691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount boolean wasInMap = false; 765d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (propertyMap != null) { 766691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount wasInMap = propertyMap.containsKey(mPropertyName); 767691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (wasInMap) { 768691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount setterOrGetter = propertyMap.get(mPropertyName); 769691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 770d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 771691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!wasInMap) { 772d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase setterOrGetter = getPropertyFunction(targetClass, prefix, valueType); 773d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (propertyMap == null) { 774d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMap = new HashMap<String, Method>(); 775d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMapMap.put(targetClass, propertyMap); 776d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 777d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMap.put(mPropertyName, setterOrGetter); 778d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 779d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 780d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return setterOrGetter; 781d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 782d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 783d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 784d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Utility function to get the setter from targetClass 785d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The Class on which the requested method should exist. 786d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 7876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 78816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount Class<?> propertyType = mConverter == null ? mValueType : mConverter.getTargetType(); 78916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType); 790d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 791d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 792d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 793d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Utility function to get the getter from targetClass 794d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 795d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private void setupGetter(Class targetClass) { 796d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null); 797d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 798d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 799d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 800a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function (called from ObjectAnimator) to set up the setter and getter 801d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * prior to running the animation. If the setter has not been manually set for this 802d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * object, it will be derived automatically given the property name, target object, and 803d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * types of values supplied. If no getter has been set, it will be supplied iff any of the 804d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * supplied values was null. If there is a null value, then the getter (supplied or derived) 805d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * will be called to set those null values to the current value of the property 806d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the target object. 807d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param target The object on which the setter (and possibly getter) exist. 808d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 809d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void setupSetterAndGetter(Object target) { 810b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 811b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // check to make sure that mProperty is on the class of target 812b39f051631250c49936a475d0e64584afb7f1b93Chet Haase try { 81316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount Object testValue = null; 814d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar List<Keyframe> keyframes = mKeyframes.getKeyframes(); 815984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int keyframeCount = keyframes == null ? 0 : keyframes.size(); 816984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount for (int i = 0; i < keyframeCount; i++) { 817984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframe kf = keyframes.get(i); 8188619f48fb353740f7fd3f6eaa86fe493377e6cadYigit Boyar if (!kf.hasValue() || kf.valueWasSetOnStart()) { 81916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount if (testValue == null) { 82016d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount testValue = convertBack(mProperty.get(target)); 82116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 82216d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount kf.setValue(testValue); 8238619f48fb353740f7fd3f6eaa86fe493377e6cadYigit Boyar kf.setValueWasSetOnStart(true); 824b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 825b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 826b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 827b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } catch (ClassCastException e) { 828db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase Log.w("PropertyValuesHolder","No such property (" + mProperty.getName() + 829b39f051631250c49936a475d0e64584afb7f1b93Chet Haase ") on target object " + target + ". Trying reflection instead"); 830b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = null; 831b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 832b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 833691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // We can't just say 'else' here because the catch statement sets mProperty to null. 834691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (mProperty == null) { 835691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Class targetClass = target.getClass(); 836691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (mSetter == null) { 837691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount setupSetter(targetClass); 838691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 839691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount List<Keyframe> keyframes = mKeyframes.getKeyframes(); 840691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount int keyframeCount = keyframes == null ? 0 : keyframes.size(); 841691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount for (int i = 0; i < keyframeCount; i++) { 842691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Keyframe kf = keyframes.get(i); 843691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!kf.hasValue() || kf.valueWasSetOnStart()) { 844db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (mGetter == null) { 845691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount setupGetter(targetClass); 846691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (mGetter == null) { 847691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // Already logged the error - just return to avoid NPE 848691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount return; 849691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 850691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 851691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount try { 852691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Object value = convertBack(mGetter.invoke(target)); 853691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount kf.setValue(value); 854691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount kf.setValueWasSetOnStart(true); 855691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (InvocationTargetException e) { 856691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Log.e("PropertyValuesHolder", e.toString()); 857691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (IllegalAccessException e) { 858691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Log.e("PropertyValuesHolder", e.toString()); 859db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 860d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 861d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 862d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 863d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 864d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 86516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount private Object convertBack(Object value) { 86616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount if (mConverter != null) { 86742516d19db936b10874c27e16eeacda041af01f9George Mount if (!(mConverter instanceof BidirectionalTypeConverter)) { 86816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount throw new IllegalArgumentException("Converter " 86916d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount + mConverter.getClass().getName() 87042516d19db936b10874c27e16eeacda041af01f9George Mount + " must be a BidirectionalTypeConverter"); 87116d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 87242516d19db936b10874c27e16eeacda041af01f9George Mount value = ((BidirectionalTypeConverter) mConverter).convertBack(value); 87316d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 87416d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount return value; 87516d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount } 87616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount 877d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 87821cd1389d2ef218b20994b617c57af120841a57fChet Haase * Utility function to set the value stored in a particular Keyframe. The value used is 87921cd1389d2ef218b20994b617c57af120841a57fChet Haase * whatever the value is for the property name specified in the keyframe on the target object. 88021cd1389d2ef218b20994b617c57af120841a57fChet Haase * 88121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The target object from which the current value should be extracted. 88221cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param kf The keyframe which holds the property name and value. 88321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 88421cd1389d2ef218b20994b617c57af120841a57fChet Haase private void setupValue(Object target, Keyframe kf) { 885b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 88616d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount Object value = convertBack(mProperty.get(target)); 88716d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount kf.setValue(value); 888406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase } else { 889406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase try { 890db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (mGetter == null) { 891406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase Class targetClass = target.getClass(); 892406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase setupGetter(targetClass); 893406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase if (mGetter == null) { 894406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase // Already logged the error - just return to avoid NPE 895406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase return; 896406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase } 897db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 898406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase Object value = convertBack(mGetter.invoke(target)); 899406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase kf.setValue(value); 900406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase } catch (InvocationTargetException e) { 901406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase Log.e("PropertyValuesHolder", e.toString()); 902406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase } catch (IllegalAccessException e) { 903406a02b59d3a8f9890509200f048c23c3b3200b7Chet Haase Log.e("PropertyValuesHolder", e.toString()); 90421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 90521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 90621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 90721cd1389d2ef218b20994b617c57af120841a57fChet Haase 90821cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 909a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This function is called by ObjectAnimator when setting the start values for an animation. 91021cd1389d2ef218b20994b617c57af120841a57fChet Haase * The start values are set according to the current values in the target object. The 91121cd1389d2ef218b20994b617c57af120841a57fChet Haase * property whose value is extracted is whatever is specified by the propertyName of this 91221cd1389d2ef218b20994b617c57af120841a57fChet Haase * PropertyValuesHolder object. 91321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 91421cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The object which holds the start values that should be set. 91521cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 91621cd1389d2ef218b20994b617c57af120841a57fChet Haase void setupStartValue(Object target) { 917d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar List<Keyframe> keyframes = mKeyframes.getKeyframes(); 918984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (!keyframes.isEmpty()) { 919984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount setupValue(target, keyframes.get(0)); 920984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 92121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 92221cd1389d2ef218b20994b617c57af120841a57fChet Haase 92321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 924a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This function is called by ObjectAnimator when setting the end values for an animation. 92521cd1389d2ef218b20994b617c57af120841a57fChet Haase * The end values are set according to the current values in the target object. The 92621cd1389d2ef218b20994b617c57af120841a57fChet Haase * property whose value is extracted is whatever is specified by the propertyName of this 92721cd1389d2ef218b20994b617c57af120841a57fChet Haase * PropertyValuesHolder object. 92821cd1389d2ef218b20994b617c57af120841a57fChet Haase * 92921cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The object which holds the start values that should be set. 93021cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 93121cd1389d2ef218b20994b617c57af120841a57fChet Haase void setupEndValue(Object target) { 932d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar List<Keyframe> keyframes = mKeyframes.getKeyframes(); 933984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (!keyframes.isEmpty()) { 934984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount setupValue(target, keyframes.get(keyframes.size() - 1)); 935984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 93621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 93721cd1389d2ef218b20994b617c57af120841a57fChet Haase 93821cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 93921cd1389d2ef218b20994b617c57af120841a57fChet Haase public PropertyValuesHolder clone() { 9407c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 9417c608f25d494c8a0a671e7373efbb47ca635367eChet Haase PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); 9427c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mPropertyName = mPropertyName; 943b39f051631250c49936a475d0e64584afb7f1b93Chet Haase newPVH.mProperty = mProperty; 944984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount newPVH.mKeyframes = mKeyframes.clone(); 9457c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mEvaluator = mEvaluator; 9467c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 9477c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (CloneNotSupportedException e) { 9487c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // won't reach here 9497c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return null; 95021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 95121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 9527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 95321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 954d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Internal function to set the value on the target object, using the setter set up 955a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 956a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 957d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * according to the name of the property. 958d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param target The target object on which the value is set 959d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 960d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void setAnimatedValue(Object target) { 961b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 962b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, getAnimatedValue()); 963b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 964d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mSetter != null) { 965d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 9667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = getAnimatedValue(); 967d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mSetter.invoke(target, mTmpValueArray); 968d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (InvocationTargetException e) { 969d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 970d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (IllegalAccessException e) { 971d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 972d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 973d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 974d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 975d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 976d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 977a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used 978d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * to calculate animated values. 979d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 980d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void init() { 981d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mEvaluator == null) { 982b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // We already handle int and float automatically, but not their Object 9837c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // equivalents 9847c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mEvaluator = (mValueType == Integer.class) ? sIntEvaluator : 9857c608f25d494c8a0a671e7373efbb47ca635367eChet Haase (mValueType == Float.class) ? sFloatEvaluator : 9867c608f25d494c8a0a671e7373efbb47ca635367eChet Haase null; 9877c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9887c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mEvaluator != null) { 9897c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // KeyframeSet knows how to evaluate the common types - only give it a custom 990b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // evaluator if one has been set on this class 991984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes.setEvaluator(mEvaluator); 992d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 993d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 994d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 995d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 996d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * The TypeEvaluator will be automatically determined based on the type of values 997d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * supplied to PropertyValuesHolder. The evaluator can be manually set, however, if so 998d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * desired. This may be important in cases where either the type of the values supplied 999d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * do not match the way that they should be interpolated between, or if the values 1000d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * are of a custom type or one not currently understood by the animation system. Currently, 1001b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase * only values of type float and int (and their Object equivalents: Float 1002d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. 1003d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param evaluator 1004d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 10057c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public void setEvaluator(TypeEvaluator evaluator) { 1006d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mEvaluator = evaluator; 1007984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes.setEvaluator(evaluator); 1008d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 1009d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 1010d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 1011d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Function used to calculate the value according to the evaluator set up for 1012a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). 1013d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 1014d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param fraction The elapsed, interpolated fraction of the animation. 1015d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 10167c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 1017984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Object value = mKeyframes.getValue(fraction); 101816d2c9cc6bd67131d9921fbc14a69d88f48f48caGeorge Mount mAnimatedValue = mConverter == null ? value : mConverter.convert(value); 1019d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 1020d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 1021d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 1022d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Sets the name of the property that will be animated. This name is used to derive 1023d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a setter function that will be called to set animated values. 1024d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * For example, a property name of <code>foo</code> will result 1025d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * in a call to the function <code>setFoo()</code> on the target object. If either 1026d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will 1027d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * also be derived and called. 1028d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 1029d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <p>Note that the setter function derived from this property name 1030d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * must take the same parameter type as the 1031d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to 1032d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * the setter function will fail.</p> 1033d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 1034d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyName The name of the property being animated. 1035d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 1036d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase public void setPropertyName(String propertyName) { 1037d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mPropertyName = propertyName; 1038d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 1039d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 1040d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 1041b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Sets the property that will be animated. 1042b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 1043b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * <p>Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property 1044b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * must exist on the target object specified in that ObjectAnimator.</p> 1045b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 1046b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. 1047b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 1048b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public void setProperty(Property property) { 1049b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = property; 1050b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1051b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 1052b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 1053d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Gets the name of the property that will be animated. This name will be used to derive 1054d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a setter function that will be called to set animated values. 1055d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * For example, a property name of <code>foo</code> will result 1056d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * in a call to the function <code>setFoo()</code> on the target object. If either 1057d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will 1058d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * also be derived and called. 1059d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 1060d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase public String getPropertyName() { 1061d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return mPropertyName; 1062d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 1063d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 1064d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 1065a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value 1066d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * most recently calculated in calculateValue(). 1067d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return 1068d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 1069d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Object getAnimatedValue() { 1070d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return mAnimatedValue; 1071d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 10727c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1073766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu /** 1074766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * PropertyValuesHolder is Animators use to hold internal animation related data. 1075766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * Therefore, in order to replicate the animation behavior, we need to get data out of 1076766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * PropertyValuesHolder. 1077766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * @hide 1078766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu */ 1079766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public void getPropertyValues(PropertyValues values) { 1080766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu init(); 1081766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.propertyName = mPropertyName; 1082766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.type = mValueType; 1083766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.startValue = mKeyframes.getValue(0); 1084766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (values.startValue instanceof PathParser.PathData) { 1085766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // PathData evaluator returns the same mutable PathData object when query fraction, 1086766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // so we have to make a copy here. 1087766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.startValue = new PathParser.PathData((PathParser.PathData) values.startValue); 1088766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1089766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.endValue = mKeyframes.getValue(1); 1090766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (values.endValue instanceof PathParser.PathData) { 1091766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // PathData evaluator returns the same mutable PathData object when query fraction, 1092766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // so we have to make a copy here. 1093766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.endValue = new PathParser.PathData((PathParser.PathData) values.endValue); 1094766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1095766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: We need a better way to get data out of keyframes. 1096766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mKeyframes instanceof PathKeyframes.FloatKeyframesBase 1097a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu || mKeyframes instanceof PathKeyframes.IntKeyframesBase 1098a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu || (mKeyframes.getKeyframes() != null && mKeyframes.getKeyframes().size() > 2)) { 1099a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu // When a pvh has more than 2 keyframes, that means there are intermediate values in 1100a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu // addition to start/end values defined for animators. Another case where such 1101a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu // intermediate values are defined is when animator has a path to animate along. In 1102a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu // these cases, a data source is needed to capture these intermediate values. 1103766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.dataSource = new PropertyValues.DataSource() { 1104766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu @Override 1105766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public Object getValueAtFraction(float fraction) { 1106766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return mKeyframes.getValue(fraction); 1107766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1108766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu }; 1109766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else { 1110766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values.dataSource = null; 1111766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1112766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1113766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 111494db09917a17976135e2c63d8e4171c54730c079Doris Liu /** 111594db09917a17976135e2c63d8e4171c54730c079Doris Liu * @hide 111694db09917a17976135e2c63d8e4171c54730c079Doris Liu */ 111794db09917a17976135e2c63d8e4171c54730c079Doris Liu public Class getValueType() { 111894db09917a17976135e2c63d8e4171c54730c079Doris Liu return mValueType; 111994db09917a17976135e2c63d8e4171c54730c079Doris Liu } 112094db09917a17976135e2c63d8e4171c54730c079Doris Liu 1121e9140a72b1059574046a624b471b2c3a35806496Chet Haase @Override 1122e9140a72b1059574046a624b471b2c3a35806496Chet Haase public String toString() { 1123984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return mPropertyName + ": " + mKeyframes.toString(); 1124e9140a72b1059574046a624b471b2c3a35806496Chet Haase } 1125e9140a72b1059574046a624b471b2c3a35806496Chet Haase 11266e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase /** 11276e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * Utility method to derive a setter/getter method name from a property name, where the 11286e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * prefix is typically "set" or "get" and the first letter of the property name is 11296e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * capitalized. 11306e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * 11316e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @param prefix The precursor to the method name, before the property name begins, typically 11326e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * "set" or "get". 11336e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @param propertyName The name of the property that represents the bulk of the method name 11346e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * after the prefix. The first letter of this word will be capitalized in the resulting 11356e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * method name. 11366e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @return String the property name converted to a method name according to the conventions 11376e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * specified above. 11386e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase */ 11396e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase static String getMethodName(String prefix, String propertyName) { 1140b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (propertyName == null || propertyName.length() == 0) { 1141b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // shouldn't get here 1142b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return prefix; 1143b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1144b39f051631250c49936a475d0e64584afb7f1b93Chet Haase char firstLetter = Character.toUpperCase(propertyName.charAt(0)); 11456e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String theRest = propertyName.substring(1); 11466e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return prefix + firstLetter + theRest; 11476e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 11486e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 11497c608f25d494c8a0a671e7373efbb47ca635367eChet Haase static class IntPropertyValuesHolder extends PropertyValuesHolder { 11507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1151b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // Cache JNI functions to avoid looking them up twice 1152fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = 1153fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat new HashMap<Class, HashMap<String, Long>>(); 1154fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat long mJniSetter; 1155b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private IntProperty mIntProperty; 11566e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 1157984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes.IntKeyframes mIntKeyframes; 11587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int mIntAnimatedValue; 11597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1160984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public IntPropertyValuesHolder(String propertyName, Keyframes.IntKeyframes keyframes) { 11617c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 11627c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mValueType = int.class; 1163984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 1164984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mIntKeyframes = keyframes; 11657c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 11667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1167984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public IntPropertyValuesHolder(Property property, Keyframes.IntKeyframes keyframes) { 1168b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 1169b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mValueType = int.class; 1170984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 1171984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mIntKeyframes = keyframes; 1172b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof IntProperty) { 1173b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty = (IntProperty) mProperty; 1174b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1175b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1176b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 11777c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public IntPropertyValuesHolder(String propertyName, int... values) { 11787c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 11797c608f25d494c8a0a671e7373efbb47ca635367eChet Haase setIntValues(values); 1180691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase } 1181691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase 1182b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public IntPropertyValuesHolder(Property property, int... values) { 1183b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 1184b39f051631250c49936a475d0e64584afb7f1b93Chet Haase setIntValues(values); 1185b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof IntProperty) { 1186b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty = (IntProperty) mProperty; 1187b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1188b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1189b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 1190691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase @Override 11919f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu public void setProperty(Property property) { 11929f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu if (property instanceof IntProperty) { 11939f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu mIntProperty = (IntProperty) property; 11949f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } else { 11959f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu super.setProperty(property); 11969f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } 11979f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } 11989f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu 11999f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu @Override 1200691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase public void setIntValues(int... values) { 1201691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase super.setIntValues(values); 1202984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mIntKeyframes = (Keyframes.IntKeyframes) mKeyframes; 12037c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12047c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 12057c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 12067c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 1207984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mIntAnimatedValue = mIntKeyframes.getIntValue(fraction); 12087c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 12107c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 12117c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Object getAnimatedValue() { 12127c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return mIntAnimatedValue; 12137c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12147c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 12157c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 12167c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public IntPropertyValuesHolder clone() { 12177c608f25d494c8a0a671e7373efbb47ca635367eChet Haase IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone(); 1218984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount newPVH.mIntKeyframes = (Keyframes.IntKeyframes) newPVH.mKeyframes; 12197c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 12207c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12217c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 12227c608f25d494c8a0a671e7373efbb47ca635367eChet Haase /** 12237c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * Internal function to set the value on the target object, using the setter set up 12247c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 12257c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 12267c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * according to the name of the property. 12277c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * @param target The target object on which the value is set 12287c608f25d494c8a0a671e7373efbb47ca635367eChet Haase */ 12297c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 12307c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void setAnimatedValue(Object target) { 1231b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mIntProperty != null) { 1232b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty.setValue(target, mIntAnimatedValue); 1233b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1234b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1235b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 1236b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, mIntAnimatedValue); 1237b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1238b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 12396e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 12406e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase nCallIntMethod(target, mJniSetter, mIntAnimatedValue); 12416e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return; 12426e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12437c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mSetter != null) { 12447c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 12457c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = mIntAnimatedValue; 12467c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mSetter.invoke(target, mTmpValueArray); 12477c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (InvocationTargetException e) { 12487c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 12497c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (IllegalAccessException e) { 12507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 12517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12537c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12546e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 12556e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase @Override 12566e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 1257b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 1258b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1259b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 12606e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Check new static hashmap<propName, int> for setter method 1261691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount synchronized(sJNISetterPropertyMap) { 1262fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); 1263691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount boolean wasInMap = false; 12646e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap != null) { 1265691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount wasInMap = propertyMap.containsKey(mPropertyName); 1266691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (wasInMap) { 1267691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Long jniSetter = propertyMap.get(mPropertyName); 1268691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (jniSetter != null) { 1269691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = jniSetter; 1270691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 12716e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12726e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 1273691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!wasInMap) { 12746e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName("set", mPropertyName); 1275691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount try { 1276691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = nGetIntMethod(targetClass, methodName); 1277691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (NoSuchMethodError e) { 1278691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // Couldn't find it via JNI - try reflection next. Probably means the method 1279691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // doesn't exist, or the type is wrong. An error will be logged later if 1280691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // reflection fails as well. 12816e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 1282691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (propertyMap == null) { 1283691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap = new HashMap<String, Long>(); 1284691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount sJNISetterPropertyMap.put(targetClass, propertyMap); 1285691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 1286691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap.put(mPropertyName, mJniSetter); 12876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12886e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12896e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 12906e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Couldn't find method through fast JNI approach - just use reflection 12916e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase super.setupSetter(targetClass); 12926e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12936e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 12947c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 12957c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 12967c608f25d494c8a0a671e7373efbb47ca635367eChet Haase static class FloatPropertyValuesHolder extends PropertyValuesHolder { 12977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1298b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // Cache JNI functions to avoid looking them up twice 1299fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = 1300fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat new HashMap<Class, HashMap<String, Long>>(); 1301fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat long mJniSetter; 1302b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private FloatProperty mFloatProperty; 13036e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 1304984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes.FloatKeyframes mFloatKeyframes; 13057c608f25d494c8a0a671e7373efbb47ca635367eChet Haase float mFloatAnimatedValue; 13067c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1307984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public FloatPropertyValuesHolder(String propertyName, Keyframes.FloatKeyframes keyframes) { 13087c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 13097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mValueType = float.class; 1310984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 1311984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mFloatKeyframes = keyframes; 13127c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13137c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 1314984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public FloatPropertyValuesHolder(Property property, Keyframes.FloatKeyframes keyframes) { 1315b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 1316b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mValueType = float.class; 1317984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 1318984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mFloatKeyframes = keyframes; 1319b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof FloatProperty) { 1320b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty = (FloatProperty) mProperty; 1321b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1322b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1323b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 13247c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public FloatPropertyValuesHolder(String propertyName, float... values) { 13257c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 13267c608f25d494c8a0a671e7373efbb47ca635367eChet Haase setFloatValues(values); 1327691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase } 1328691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase 1329b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public FloatPropertyValuesHolder(Property property, float... values) { 1330b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 1331b39f051631250c49936a475d0e64584afb7f1b93Chet Haase setFloatValues(values); 1332b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof FloatProperty) { 1333b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty = (FloatProperty) mProperty; 1334b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1335b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1336b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 1337691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase @Override 13389f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu public void setProperty(Property property) { 13399f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu if (property instanceof FloatProperty) { 13409f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu mFloatProperty = (FloatProperty) property; 13419f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } else { 13429f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu super.setProperty(property); 13439f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } 13449f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } 13459f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu 13469f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu @Override 1347691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase public void setFloatValues(float... values) { 1348691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase super.setFloatValues(values); 1349984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes; 13507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 13527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 13537c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 1354984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mFloatAnimatedValue = mFloatKeyframes.getFloatValue(fraction); 13557c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13567c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 13577c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 13587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Object getAnimatedValue() { 13597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return mFloatAnimatedValue; 13607c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13617c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 13627c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 13637c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public FloatPropertyValuesHolder clone() { 13647c608f25d494c8a0a671e7373efbb47ca635367eChet Haase FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone(); 1365984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount newPVH.mFloatKeyframes = (Keyframes.FloatKeyframes) newPVH.mKeyframes; 13667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 13677c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13687c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 13697c608f25d494c8a0a671e7373efbb47ca635367eChet Haase /** 13707c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * Internal function to set the value on the target object, using the setter set up 13717c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 13727c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 13737c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * according to the name of the property. 13747c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * @param target The target object on which the value is set 13757c608f25d494c8a0a671e7373efbb47ca635367eChet Haase */ 13767c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 13777c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void setAnimatedValue(Object target) { 1378b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mFloatProperty != null) { 1379b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty.setValue(target, mFloatAnimatedValue); 1380b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1381b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 1382b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 1383b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, mFloatAnimatedValue); 1384b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1385b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 13866e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 13876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue); 13886e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return; 13896e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 13907c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mSetter != null) { 13917c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 13927c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = mFloatAnimatedValue; 13937c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mSetter.invoke(target, mTmpValueArray); 13947c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (InvocationTargetException e) { 13957c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 13967c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (IllegalAccessException e) { 13977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 13987c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 13997c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 14007c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 14017c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 14026e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase @Override 14036e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 1404b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 1405b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 1406b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 14076e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Check new static hashmap<propName, int> for setter method 1408691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount synchronized (sJNISetterPropertyMap) { 1409fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); 1410691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount boolean wasInMap = false; 14116e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap != null) { 1412691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount wasInMap = propertyMap.containsKey(mPropertyName); 1413691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (wasInMap) { 1414691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Long jniSetter = propertyMap.get(mPropertyName); 1415691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (jniSetter != null) { 1416691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = jniSetter; 1417691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 14186e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 14196e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 1420691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!wasInMap) { 14216e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName("set", mPropertyName); 1422691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount try { 1423691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = nGetFloatMethod(targetClass, methodName); 1424691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (NoSuchMethodError e) { 1425691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // Couldn't find it via JNI - try reflection next. Probably means the method 1426691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // doesn't exist, or the type is wrong. An error will be logged later if 1427691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // reflection fails as well. 1428691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 1429691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (propertyMap == null) { 1430691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap = new HashMap<String, Long>(); 1431691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount sJNISetterPropertyMap.put(targetClass, propertyMap); 14326e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 1433691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap.put(mPropertyName, mJniSetter); 14346e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 14356e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 14366e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 14376e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Couldn't find method through fast JNI approach - just use reflection 14386e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase super.setupSetter(targetClass); 14396e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 14406e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 14416e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 14427c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 14436e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 14444eed52944c0fcb3afa7369aba60fb5c655580286George Mount static class MultiFloatValuesHolder extends PropertyValuesHolder { 1445fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private long mJniSetter; 1446fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = 1447fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat new HashMap<Class, HashMap<String, Long>>(); 14484eed52944c0fcb3afa7369aba60fb5c655580286George Mount 14494eed52944c0fcb3afa7369aba60fb5c655580286George Mount public MultiFloatValuesHolder(String propertyName, TypeConverter converter, 14504eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeEvaluator evaluator, Object... values) { 14514eed52944c0fcb3afa7369aba60fb5c655580286George Mount super(propertyName); 14524eed52944c0fcb3afa7369aba60fb5c655580286George Mount setConverter(converter); 14534eed52944c0fcb3afa7369aba60fb5c655580286George Mount setObjectValues(values); 14544eed52944c0fcb3afa7369aba60fb5c655580286George Mount setEvaluator(evaluator); 14554eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14564eed52944c0fcb3afa7369aba60fb5c655580286George Mount 14574eed52944c0fcb3afa7369aba60fb5c655580286George Mount public MultiFloatValuesHolder(String propertyName, TypeConverter converter, 1458984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount TypeEvaluator evaluator, Keyframes keyframes) { 14594eed52944c0fcb3afa7369aba60fb5c655580286George Mount super(propertyName); 14604eed52944c0fcb3afa7369aba60fb5c655580286George Mount setConverter(converter); 1461984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 14624eed52944c0fcb3afa7369aba60fb5c655580286George Mount setEvaluator(evaluator); 14634eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14644eed52944c0fcb3afa7369aba60fb5c655580286George Mount 14654eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 14664eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Internal function to set the value on the target object, using the setter set up 14674eed52944c0fcb3afa7369aba60fb5c655580286George Mount * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 14684eed52944c0fcb3afa7369aba60fb5c655580286George Mount * to handle turning the value calculated by ValueAnimator into a value set on the object 14694eed52944c0fcb3afa7369aba60fb5c655580286George Mount * according to the name of the property. 14704eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 14714eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param target The target object on which the value is set 14724eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 14734eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 14744eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setAnimatedValue(Object target) { 14754eed52944c0fcb3afa7369aba60fb5c655580286George Mount float[] values = (float[]) getAnimatedValue(); 14764eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParameters = values.length; 14774eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (mJniSetter != 0) { 14784eed52944c0fcb3afa7369aba60fb5c655580286George Mount switch (numParameters) { 14794eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 1: 14804eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallFloatMethod(target, mJniSetter, values[0]); 14814eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 14824eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 2: 14834eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallTwoFloatMethod(target, mJniSetter, values[0], values[1]); 14844eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 14854eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 4: 14864eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallFourFloatMethod(target, mJniSetter, values[0], values[1], 14874eed52944c0fcb3afa7369aba60fb5c655580286George Mount values[2], values[3]); 14884eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 14894eed52944c0fcb3afa7369aba60fb5c655580286George Mount default: { 14904eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallMultipleFloatMethod(target, mJniSetter, values); 14914eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 14924eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14934eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14944eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14954eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 14964eed52944c0fcb3afa7369aba60fb5c655580286George Mount 14974eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 14984eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Internal function (called from ObjectAnimator) to set up the setter and getter 14994eed52944c0fcb3afa7369aba60fb5c655580286George Mount * prior to running the animation. No getter can be used for multiple parameters. 15004eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 15014eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param target The object on which the setter exists. 15024eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 15034eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 15044eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setupSetterAndGetter(Object target) { 15054eed52944c0fcb3afa7369aba60fb5c655580286George Mount setupSetter(target.getClass()); 15064eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15074eed52944c0fcb3afa7369aba60fb5c655580286George Mount 15084eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 15094eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setupSetter(Class targetClass) { 15104eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (mJniSetter != 0) { 15114eed52944c0fcb3afa7369aba60fb5c655580286George Mount return; 15124eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1513691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount synchronized(sJNISetterPropertyMap) { 1514fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); 1515691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount boolean wasInMap = false; 15164eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (propertyMap != null) { 1517691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount wasInMap = propertyMap.containsKey(mPropertyName); 1518691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (wasInMap) { 1519691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Long jniSetter = propertyMap.get(mPropertyName); 1520691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (jniSetter != null) { 1521691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = jniSetter; 1522691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 15234eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15244eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1525691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!wasInMap) { 15264eed52944c0fcb3afa7369aba60fb5c655580286George Mount String methodName = getMethodName("set", mPropertyName); 15274eed52944c0fcb3afa7369aba60fb5c655580286George Mount calculateValue(0f); 15284eed52944c0fcb3afa7369aba60fb5c655580286George Mount float[] values = (float[]) getAnimatedValue(); 15294eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParams = values.length; 15304eed52944c0fcb3afa7369aba60fb5c655580286George Mount try { 15314eed52944c0fcb3afa7369aba60fb5c655580286George Mount mJniSetter = nGetMultipleFloatMethod(targetClass, methodName, numParams); 15324eed52944c0fcb3afa7369aba60fb5c655580286George Mount } catch (NoSuchMethodError e) { 15334eed52944c0fcb3afa7369aba60fb5c655580286George Mount // try without the 'set' prefix 1534691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount try { 1535691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = nGetMultipleFloatMethod(targetClass, mPropertyName, 1536691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount numParams); 1537691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (NoSuchMethodError e2) { 1538691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // just try reflection next 15394eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15404eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1541691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (propertyMap == null) { 1542691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap = new HashMap<String, Long>(); 1543691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount sJNISetterPropertyMap.put(targetClass, propertyMap); 1544691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 1545691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap.put(mPropertyName, mJniSetter); 15464eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15479f3b31b9530a2121b4557fc312972c4faa133d5eDoris Liu } 15484eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15494eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15504eed52944c0fcb3afa7369aba60fb5c655580286George Mount 15514eed52944c0fcb3afa7369aba60fb5c655580286George Mount static class MultiIntValuesHolder extends PropertyValuesHolder { 1552fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private long mJniSetter; 1553fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = 1554fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat new HashMap<Class, HashMap<String, Long>>(); 15554eed52944c0fcb3afa7369aba60fb5c655580286George Mount 15564eed52944c0fcb3afa7369aba60fb5c655580286George Mount public MultiIntValuesHolder(String propertyName, TypeConverter converter, 15574eed52944c0fcb3afa7369aba60fb5c655580286George Mount TypeEvaluator evaluator, Object... values) { 15584eed52944c0fcb3afa7369aba60fb5c655580286George Mount super(propertyName); 15594eed52944c0fcb3afa7369aba60fb5c655580286George Mount setConverter(converter); 15604eed52944c0fcb3afa7369aba60fb5c655580286George Mount setObjectValues(values); 15614eed52944c0fcb3afa7369aba60fb5c655580286George Mount setEvaluator(evaluator); 15624eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15634eed52944c0fcb3afa7369aba60fb5c655580286George Mount 15644eed52944c0fcb3afa7369aba60fb5c655580286George Mount public MultiIntValuesHolder(String propertyName, TypeConverter converter, 1565984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount TypeEvaluator evaluator, Keyframes keyframes) { 15664eed52944c0fcb3afa7369aba60fb5c655580286George Mount super(propertyName); 15674eed52944c0fcb3afa7369aba60fb5c655580286George Mount setConverter(converter); 1568984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframes = keyframes; 15694eed52944c0fcb3afa7369aba60fb5c655580286George Mount setEvaluator(evaluator); 15704eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 15714eed52944c0fcb3afa7369aba60fb5c655580286George Mount 15724eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 15734eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Internal function to set the value on the target object, using the setter set up 15744eed52944c0fcb3afa7369aba60fb5c655580286George Mount * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 15754eed52944c0fcb3afa7369aba60fb5c655580286George Mount * to handle turning the value calculated by ValueAnimator into a value set on the object 15764eed52944c0fcb3afa7369aba60fb5c655580286George Mount * according to the name of the property. 15774eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 15784eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param target The target object on which the value is set 15794eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 15804eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 15814eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setAnimatedValue(Object target) { 15824eed52944c0fcb3afa7369aba60fb5c655580286George Mount int[] values = (int[]) getAnimatedValue(); 15834eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParameters = values.length; 15844eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (mJniSetter != 0) { 15854eed52944c0fcb3afa7369aba60fb5c655580286George Mount switch (numParameters) { 15864eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 1: 15874eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallIntMethod(target, mJniSetter, values[0]); 15884eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 15894eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 2: 15904eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallTwoIntMethod(target, mJniSetter, values[0], values[1]); 15914eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 15924eed52944c0fcb3afa7369aba60fb5c655580286George Mount case 4: 15934eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallFourIntMethod(target, mJniSetter, values[0], values[1], 15944eed52944c0fcb3afa7369aba60fb5c655580286George Mount values[2], values[3]); 15954eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 15964eed52944c0fcb3afa7369aba60fb5c655580286George Mount default: { 15974eed52944c0fcb3afa7369aba60fb5c655580286George Mount nCallMultipleIntMethod(target, mJniSetter, values); 15984eed52944c0fcb3afa7369aba60fb5c655580286George Mount break; 15994eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16004eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16014eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16024eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16034eed52944c0fcb3afa7369aba60fb5c655580286George Mount 16044eed52944c0fcb3afa7369aba60fb5c655580286George Mount /** 16054eed52944c0fcb3afa7369aba60fb5c655580286George Mount * Internal function (called from ObjectAnimator) to set up the setter and getter 16064eed52944c0fcb3afa7369aba60fb5c655580286George Mount * prior to running the animation. No getter can be used for multiple parameters. 16074eed52944c0fcb3afa7369aba60fb5c655580286George Mount * 16084eed52944c0fcb3afa7369aba60fb5c655580286George Mount * @param target The object on which the setter exists. 16094eed52944c0fcb3afa7369aba60fb5c655580286George Mount */ 16104eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 16114eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setupSetterAndGetter(Object target) { 16124eed52944c0fcb3afa7369aba60fb5c655580286George Mount setupSetter(target.getClass()); 16134eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16144eed52944c0fcb3afa7369aba60fb5c655580286George Mount 16154eed52944c0fcb3afa7369aba60fb5c655580286George Mount @Override 16164eed52944c0fcb3afa7369aba60fb5c655580286George Mount void setupSetter(Class targetClass) { 16174eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (mJniSetter != 0) { 16184eed52944c0fcb3afa7369aba60fb5c655580286George Mount return; 16194eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1620691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount synchronized(sJNISetterPropertyMap) { 1621fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); 1622691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount boolean wasInMap = false; 16234eed52944c0fcb3afa7369aba60fb5c655580286George Mount if (propertyMap != null) { 1624691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount wasInMap = propertyMap.containsKey(mPropertyName); 1625691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (wasInMap) { 1626691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount Long jniSetter = propertyMap.get(mPropertyName); 1627691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (jniSetter != null) { 1628691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = jniSetter; 1629691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 16304eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16314eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1632691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (!wasInMap) { 16334eed52944c0fcb3afa7369aba60fb5c655580286George Mount String methodName = getMethodName("set", mPropertyName); 16344eed52944c0fcb3afa7369aba60fb5c655580286George Mount calculateValue(0f); 16354eed52944c0fcb3afa7369aba60fb5c655580286George Mount int[] values = (int[]) getAnimatedValue(); 16364eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParams = values.length; 16374eed52944c0fcb3afa7369aba60fb5c655580286George Mount try { 16384eed52944c0fcb3afa7369aba60fb5c655580286George Mount mJniSetter = nGetMultipleIntMethod(targetClass, methodName, numParams); 16394eed52944c0fcb3afa7369aba60fb5c655580286George Mount } catch (NoSuchMethodError e) { 16404eed52944c0fcb3afa7369aba60fb5c655580286George Mount // try without the 'set' prefix 1641691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount try { 1642691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount mJniSetter = nGetMultipleIntMethod(targetClass, mPropertyName, 1643691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount numParams); 1644691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } catch (NoSuchMethodError e2) { 1645691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount // couldn't find it. 16464eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16474eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 1648691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount if (propertyMap == null) { 1649691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap = new HashMap<String, Long>(); 1650691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount sJNISetterPropertyMap.put(targetClass, propertyMap); 1651691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount } 1652691487d2c370dc2c7dbf360a25244b99651c18afGeorge Mount propertyMap.put(mPropertyName, mJniSetter); 16534eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16544eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16554eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16564eed52944c0fcb3afa7369aba60fb5c655580286George Mount } 16574eed52944c0fcb3afa7369aba60fb5c655580286George Mount 1658c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 1659c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Convert from PointF to float[] for multi-float setters along a Path. 1660c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 1661c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount private static class PointFToFloatArray extends TypeConverter<PointF, float[]> { 1662c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount private float[] mCoordinates = new float[2]; 1663c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1664c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public PointFToFloatArray() { 1665c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount super(PointF.class, float[].class); 1666c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 1667c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1668c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount @Override 1669c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public float[] convert(PointF value) { 1670c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount mCoordinates[0] = value.x; 1671c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount mCoordinates[1] = value.y; 1672c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return mCoordinates; 1673c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 1674c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount }; 1675c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1676c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount /** 1677c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount * Convert from PointF to int[] for multi-int setters along a Path. 1678c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount */ 1679c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount private static class PointFToIntArray extends TypeConverter<PointF, int[]> { 1680c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount private int[] mCoordinates = new int[2]; 1681c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1682c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public PointFToIntArray() { 1683c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount super(PointF.class, int[].class); 1684c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 1685c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1686c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount @Override 1687c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount public int[] convert(PointF value) { 1688c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount mCoordinates[0] = Math.round(value.x); 1689c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount mCoordinates[1] = Math.round(value.y); 1690c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return mCoordinates; 1691c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 1692c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount }; 1693c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 1694766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu /** 1695766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * @hide 1696766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu */ 1697766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public static class PropertyValues { 1698766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public String propertyName; 1699766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public Class type; 1700766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public Object startValue; 1701766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public Object endValue; 1702766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public DataSource dataSource = null; 1703766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public interface DataSource { 1704766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu Object getValueAtFraction(float fraction); 1705766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1706766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public String toString() { 1707766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return ("property name: " + propertyName + ", type: " + type + ", startValue: " 1708766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu + startValue.toString() + ", endValue: " + endValue.toString()); 1709766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1710766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1711766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1712fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private long nGetIntMethod(Class targetClass, String methodName); 1713fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private long nGetFloatMethod(Class targetClass, String methodName); 1714fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private long nGetMultipleIntMethod(Class targetClass, String methodName, 17154eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParams); 1716fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private long nGetMultipleFloatMethod(Class targetClass, String methodName, 17174eed52944c0fcb3afa7369aba60fb5c655580286George Mount int numParams); 1718fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallIntMethod(Object target, long methodID, int arg); 1719fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallFloatMethod(Object target, long methodID, float arg); 1720fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallTwoIntMethod(Object target, long methodID, int arg1, int arg2); 1721fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallFourIntMethod(Object target, long methodID, int arg1, int arg2, 17224eed52944c0fcb3afa7369aba60fb5c655580286George Mount int arg3, int arg4); 1723fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallMultipleIntMethod(Object target, long methodID, int[] args); 1724fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallTwoFloatMethod(Object target, long methodID, float arg1, 17254eed52944c0fcb3afa7369aba60fb5c655580286George Mount float arg2); 1726fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallFourFloatMethod(Object target, long methodID, float arg1, 17274eed52944c0fcb3afa7369aba60fb5c655580286George Mount float arg2, float arg3, float arg4); 1728fbb35fb39eb74c6fa7ba6804faeaccb80483be14Ashok Bhat native static private void nCallMultipleFloatMethod(Object target, long methodID, float[] args); 1729c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount} 1730