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 19b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.FloatProperty; 20b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.IntProperty; 21d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport android.util.Log; 22b39f051631250c49936a475d0e64584afb7f1b93Chet Haaseimport android.util.Property; 23d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 24d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.lang.reflect.InvocationTargetException; 25d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.lang.reflect.Method; 26d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.util.HashMap; 27d953d08e9299072130d9f4411cbcf6678bbce822Chet Haaseimport java.util.concurrent.locks.ReentrantReadWriteLock; 28d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 29d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase/** 3021cd1389d2ef218b20994b617c57af120841a57fChet Haase * This class holds information about a property and the values that that property 3121cd1389d2ef218b20994b617c57af120841a57fChet Haase * should take on during an animation. PropertyValuesHolder objects can be used to create 32a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations with ValueAnimator or ObjectAnimator that operate on several different properties 3321cd1389d2ef218b20994b617c57af120841a57fChet Haase * in parallel. 34d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 352794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haasepublic class PropertyValuesHolder implements Cloneable { 36d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 37d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 38d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The name of the property associated with the values. This need not be a real property, 39a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * unless this object is being used with ObjectAnimator. But this is the name by which 40a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator. 41d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 426e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String mPropertyName; 43d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 44d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 45b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @hide 46b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 47b39f051631250c49936a475d0e64584afb7f1b93Chet Haase protected Property mProperty; 48b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 49b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 50a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * The setter function, if needed. ObjectAnimator hands off this functionality to 51d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * PropertyValuesHolder, since it holds all of the per-property information. This 5237f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase * property is automatically 53a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. 54d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 557c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Method mSetter = null; 56d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 57d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 58a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * The getter function, if needed. ObjectAnimator hands off this functionality to 59d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * PropertyValuesHolder, since it holds all of the per-property information. This 6037f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase * property is automatically 61a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. 62d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The getter is only derived and used if one of the values is null. 63d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 64d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method mGetter = null; 65d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 66d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 67d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The type of values supplied. This information is used both in deriving the setter/getter 68d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * functions and in deriving the type of TypeEvaluator. 69d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 707c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Class mValueType; 71d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 72d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 73d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The set of keyframes (time/value pairs) that define this animation. 74d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 757c608f25d494c8a0a671e7373efbb47ca635367eChet Haase KeyframeSet mKeyframeSet = null; 76d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 77d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 78b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // type evaluators for the primitive types handled by this implementation 79d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); 80d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); 81d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 82d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // We try several different types when searching for appropriate setter/getter functions. 83d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // The caller may have supplied values in a type that does not match the setter/getter 84d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // functions (such as the integers 0 and 1 to represent floating point values for alpha). 85d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Also, the use of generics in constructors means that we end up with the Object versions 86d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // of primitive types (Float vs. float). But most likely, the setter/getter functions 87d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // will take primitive types instead. 88d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // So we supply an ordered array of other types to try before giving up. 89d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class, 90d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Double.class, Integer.class}; 91d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class, 92d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Float.class, Double.class}; 93d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static Class[] DOUBLE_VARIANTS = {double.class, Double.class, float.class, int.class, 94d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Float.class, Integer.class}; 95d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 96d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // These maps hold all property entries for a particular class. This map 97d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // is used to speed up property/setter/getter lookups for a given class/property 98d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // combination. No need to use reflection on the combination more than once. 99d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final HashMap<Class, HashMap<String, Method>> sSetterPropertyMap = 100d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase new HashMap<Class, HashMap<String, Method>>(); 101d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private static final HashMap<Class, HashMap<String, Method>> sGetterPropertyMap = 102d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase new HashMap<Class, HashMap<String, Method>>(); 103d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 104d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // This lock is used to ensure that only one thread is accessing the property maps 105d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // at a time. 1066e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase final ReentrantReadWriteLock mPropertyMapLock = new ReentrantReadWriteLock(); 107d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 108d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Used to pass single value to varargs parameter in setter invocation 1096e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase final Object[] mTmpValueArray = new Object[1]; 110d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 111d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 112d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The type evaluator used to calculate the animated values. This evaluator is determined 113d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * automatically based on the type of the start/end objects passed into the constructor, 114b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase * but the system only knows about the primitive types int and float. Any other 115d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * type will need to set the evaluator to a custom evaluator for that type. 116d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 117d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private TypeEvaluator mEvaluator; 118d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 119d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 120d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The value most recently calculated by calculateValue(). This is set during 121a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * that function and might be retrieved later either by ValueAnimator.animatedValue() or 122a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * by the property-setting logic in ObjectAnimator.animatedValue(). 123d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 124d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Object mAnimatedValue; 125d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 126d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 1272794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Internal utility constructor, used by the factory methods to set the property name. 1282794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property for this holder. 129d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 1302794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase private PropertyValuesHolder(String propertyName) { 1312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mPropertyName = propertyName; 1322794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 1332794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 1342794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 135b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Internal utility constructor, used by the factory methods to set the property. 136b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property for this holder. 137b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 138b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private PropertyValuesHolder(Property property) { 139b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = property; 140b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property != null) { 141b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mPropertyName = property.getName(); 142b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 143b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 144b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 145b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 1462794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 1472794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of int values. 1482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 1492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 1502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 1512794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 1522794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofInt(String propertyName, int... values) { 153b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new IntPropertyValuesHolder(propertyName, values); 154b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 155b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 156b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 157b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 158b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of int values. 159b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 160b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 161b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 162b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 163b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values) { 164b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new IntPropertyValuesHolder(property, values); 1652794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 1662794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 1672794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 1682794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 1692794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of float values. 1702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 1712794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 1722794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 1732794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 1742794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofFloat(String propertyName, float... values) { 175b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new FloatPropertyValuesHolder(propertyName, values); 176b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 177b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 178b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 179b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 180b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of float values. 181b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 182b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 183b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 184b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 185b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) { 186b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new FloatPropertyValuesHolder(property, values); 1872794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 1882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 1892794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 1902794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder with a given property name and 1912794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * set of Object values. This variant also takes a TypeEvaluator because the system 192b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * cannot automatically interpolate between objects of unknown type. 1932794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 1942794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param propertyName The name of the property being animated. 1952794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param evaluator A TypeEvaluator that will be called on each animation frame to 196b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * provide the necessary interpolation between the Object values to derive the animated 1972794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * value. 1982794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values The values that the named property will animate between. 1992794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 2002794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 2012794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, 2022794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase Object... values) { 2032794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); 2042794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase pvh.setObjectValues(values); 2052794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase pvh.setEvaluator(evaluator); 2062794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase return pvh; 207d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 208d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 209d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 210b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder with a given property and 211b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * set of Object values. This variant also takes a TypeEvaluator because the system 212b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * cannot automatically interpolate between objects of unknown type. 213b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 214b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. Should not be null. 215b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param evaluator A TypeEvaluator that will be called on each animation frame to 216b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * provide the necessary interpolation between the Object values to derive the animated 217b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * value. 218b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The values that the property will animate between. 219b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @return PropertyValuesHolder The constructed PropertyValuesHolder object. 220b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 221b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static <V> PropertyValuesHolder ofObject(Property property, 222b39f051631250c49936a475d0e64584afb7f1b93Chet Haase TypeEvaluator<V> evaluator, V... values) { 223b39f051631250c49936a475d0e64584afb7f1b93Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(property); 224b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.setObjectValues(values); 225b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.setEvaluator(evaluator); 226b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return pvh; 227b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 228b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 229b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 2302794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Constructs and returns a PropertyValuesHolder object with the specified property name and set 2312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * of values. These values can be of any type, but the type should be consistent so that 232d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * an appropriate {@link android.animation.TypeEvaluator} can be found that matches 233d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * the common type. 234d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <p>If there is only one value, it is assumed to be the end value of an animation, 235d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and an initial value will be derived, if possible, by calling a getter function 236d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 237d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 238d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * if the PropertyValuesHolder object is used in conjunction 2391a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 2401a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 241d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * no way of determining what the value should be. 242d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyName The name of the property associated with this set of values. This 243a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * can be the actual property name to be used when using a ObjectAnimator object, or 244d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * just a name used to get animated values, such as if this object is used with an 245a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * ValueAnimator object. 246d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param values The set of values to animate between. 247d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 2482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { 2497c608f25d494c8a0a671e7373efbb47ca635367eChet Haase KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 2507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (keyframeSet instanceof IntKeyframeSet) { 2517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return new IntPropertyValuesHolder(propertyName, (IntKeyframeSet) keyframeSet); 2527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } else if (keyframeSet instanceof FloatKeyframeSet) { 2537c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return new FloatPropertyValuesHolder(propertyName, (FloatKeyframeSet) keyframeSet); 2547c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 2557c608f25d494c8a0a671e7373efbb47ca635367eChet Haase else { 2567c608f25d494c8a0a671e7373efbb47ca635367eChet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); 2577c608f25d494c8a0a671e7373efbb47ca635367eChet Haase pvh.mKeyframeSet = keyframeSet; 2587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase pvh.mValueType = ((Keyframe)values[0]).getType(); 2597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return pvh; 2607c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 261d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 262d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 263d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 264b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Constructs and returns a PropertyValuesHolder object with the specified property and set 265b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * of values. These values can be of any type, but the type should be consistent so that 266b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * an appropriate {@link android.animation.TypeEvaluator} can be found that matches 267b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * the common type. 268b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * <p>If there is only one value, it is assumed to be the end value of an animation, 269b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * and an initial value will be derived, if possible, by calling the property's 270b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * {@link android.util.Property#get(Object)} function. 271b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Also, if any value is null, the value will be filled in when the animation 272b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 273b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * if the PropertyValuesHolder object is used in conjunction with 274b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has 275b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * no way of determining what the value should be. 276b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property associated with this set of values. Should not be null. 277b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param values The set of values to animate between. 278b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 279b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { 280b39f051631250c49936a475d0e64584afb7f1b93Chet Haase KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); 281b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (keyframeSet instanceof IntKeyframeSet) { 282b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet); 283b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } else if (keyframeSet instanceof FloatKeyframeSet) { 284b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet); 285b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 286b39f051631250c49936a475d0e64584afb7f1b93Chet Haase else { 287b39f051631250c49936a475d0e64584afb7f1b93Chet Haase PropertyValuesHolder pvh = new PropertyValuesHolder(property); 288b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.mKeyframeSet = keyframeSet; 289b39f051631250c49936a475d0e64584afb7f1b93Chet Haase pvh.mValueType = ((Keyframe)values[0]).getType(); 290b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return pvh; 291b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 292b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 293b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 294b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 2952794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of ints. 296d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 297d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and an initial value will be derived, if possible, by calling a getter function 298d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 299d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 300d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * if the PropertyValuesHolder object is used in conjunction 3011a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 3021a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 303d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * no way of determining what the value should be. 3042794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 3052794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 3062794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 3072794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setIntValues(int... values) { 3082794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = int.class; 3092794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mKeyframeSet = KeyframeSet.ofInt(values); 3102794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 3112794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 3122794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 3132794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of floats. 3142794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 3152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * and an initial value will be derived, if possible, by calling a getter function 3162794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 3172794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 3182794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * if the PropertyValuesHolder object is used in conjunction 3191a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 3201a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 3212794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * no way of determining what the value should be. 3222794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 3232794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 3242794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 3252794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setFloatValues(float... values) { 3262794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = float.class; 3272794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mKeyframeSet = KeyframeSet.ofFloat(values); 3282794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 3292794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase 3302794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 3312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of Keyframes. 3322794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 3332794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 334d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 3352794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setKeyframes(Keyframe... values) { 336d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase int numKeyframes = values.length; 337d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; 3382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = ((Keyframe)values[0]).getType(); 3392794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase for (int i = 0; i < numKeyframes; ++i) { 3402794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase keyframes[i] = (Keyframe)values[i]; 341d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 342d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mKeyframeSet = new KeyframeSet(keyframes); 343d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 344d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 3452794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase /** 3462794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * Set the animated values for this object to this set of Objects. 3472794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * If there is only one value, it is assumed to be the end value of an animation, 3482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * and an initial value will be derived, if possible, by calling a getter function 3492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * on the object. Also, if any value is null, the value will be filled in when the animation 3502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * starts in the same way. This mechanism of automatically getting null values only works 3512794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * if the PropertyValuesHolder object is used in conjunction 3521a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * {@link ObjectAnimator}, and with a getter function 3531a8e404743a27da08d0f2df5480c51725c9b001aChet Haase * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has 3542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * no way of determining what the value should be. 3552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * 3562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase * @param values One or more values that the animation will animate between. 3572794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase */ 3582794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public void setObjectValues(Object... values) { 3592794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mValueType = values[0].getClass(); 3602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase mKeyframeSet = KeyframeSet.ofObject(values); 3612794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase } 362d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 363d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 364d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Determine the setter or getter function using the JavaBeans convention of setFoo or 365d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * getFoo for a property named 'foo'. This function figures out what the name of the 366d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * function should be and uses reflection to find the Method with that name on the 367d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * target object. 368d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 369d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The class to search for the method 370d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param prefix "set" or "get", depending on whether we need a setter or getter. 371d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param valueType The type of the parameter (in the case of a setter). This type 372d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * is derived from the values set on this PropertyValuesHolder. This type is used as 373d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a first guess at the parameter type, but we check for methods with several different 374d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * types to avoid problems with slight mis-matches between supplied values and actual 375d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * value types used on the setter. 376d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return Method the method associated with mPropertyName. 377d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 378d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) { 379d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // TODO: faster implementation... 380d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Method returnVal = null; 3816e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName(prefix, mPropertyName); 382d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Class args[] = null; 383d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (valueType == null) { 384d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 385d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase returnVal = targetClass.getMethod(methodName, args); 386d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (NoSuchMethodException e) { 387db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Swallow the error, log it later 388d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 389d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else { 390d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase args = new Class[1]; 391d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Class typeVariants[]; 392d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mValueType.equals(Float.class)) { 393d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = FLOAT_VARIANTS; 394d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else if (mValueType.equals(Integer.class)) { 395d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = INTEGER_VARIANTS; 396d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else if (mValueType.equals(Double.class)) { 397d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = DOUBLE_VARIANTS; 398d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } else { 399d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants = new Class[1]; 400d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase typeVariants[0] = mValueType; 401d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 402d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase for (Class typeVariant : typeVariants) { 403d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase args[0] = typeVariant; 404d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 405d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase returnVal = targetClass.getMethod(methodName, args); 40621cd1389d2ef218b20994b617c57af120841a57fChet Haase // change the value type to suit 40721cd1389d2ef218b20994b617c57af120841a57fChet Haase mValueType = typeVariant; 408d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return returnVal; 409d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (NoSuchMethodException e) { 410d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Swallow the error and keep trying other variants 411d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 412d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 413602e4d3824bf8b9cb9f817375d195b969712176aChet Haase // If we got here, then no appropriate function was found 414db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 415db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase 416db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (returnVal == null) { 417db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase Log.w("PropertyValuesHolder", "Method " + 418db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase getMethodName(prefix, mPropertyName) + "() with type " + mValueType + 419db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase " not found on target class " + targetClass); 420d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 421602e4d3824bf8b9cb9f817375d195b969712176aChet Haase 422d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return returnVal; 423d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 424d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 425d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 426d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 427d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Returns the setter or getter requested. This utility function checks whether the 428d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * requested method exists in the propertyMapMap cache. If not, it calls another 429d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * utility function to request the Method from the targetClass directly. 430d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The Class on which the requested method should exist. 431d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyMapMap The cache of setters/getters derived so far. 432d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param prefix "set" or "get", for the setter or getter. 433d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param valueType The type of parameter passed into the method (null for getter). 434d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return Method the method associated with mPropertyName. 435d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 436d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private Method setupSetterOrGetter(Class targetClass, 437d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase HashMap<Class, HashMap<String, Method>> propertyMapMap, 438d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase String prefix, Class valueType) { 439d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Method setterOrGetter = null; 440d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 441d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // Have to lock property map prior to reading it, to guard against 442d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // another thread putting something in there after we've checked it 443d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase // but before we've added an entry to it 4446e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().lock(); 445d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass); 446d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (propertyMap != null) { 447d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase setterOrGetter = propertyMap.get(mPropertyName); 448d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 449d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (setterOrGetter == null) { 450d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase setterOrGetter = getPropertyFunction(targetClass, prefix, valueType); 451d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (propertyMap == null) { 452d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMap = new HashMap<String, Method>(); 453d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMapMap.put(targetClass, propertyMap); 454d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 455d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase propertyMap.put(mPropertyName, setterOrGetter); 456d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 457d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } finally { 4586e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().unlock(); 459d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 460d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return setterOrGetter; 461d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 462d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 463d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 464d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Utility function to get the setter from targetClass 465d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param targetClass The Class on which the requested method should exist. 466d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 4676e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 468d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType); 469d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 470d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 471d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 472d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Utility function to get the getter from targetClass 473d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 474d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase private void setupGetter(Class targetClass) { 475d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null); 476d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 477d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 478d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 479a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function (called from ObjectAnimator) to set up the setter and getter 480d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * prior to running the animation. If the setter has not been manually set for this 481d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * object, it will be derived automatically given the property name, target object, and 482d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * types of values supplied. If no getter has been set, it will be supplied iff any of the 483d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * supplied values was null. If there is a null value, then the getter (supplied or derived) 484d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * will be called to set those null values to the current value of the property 485d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * on the target object. 486d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param target The object on which the setter (and possibly getter) exist. 487d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 488d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void setupSetterAndGetter(Object target) { 489b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 490b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // check to make sure that mProperty is on the class of target 491b39f051631250c49936a475d0e64584afb7f1b93Chet Haase try { 492b39f051631250c49936a475d0e64584afb7f1b93Chet Haase Object testValue = mProperty.get(target); 493b39f051631250c49936a475d0e64584afb7f1b93Chet Haase for (Keyframe kf : mKeyframeSet.mKeyframes) { 494b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (!kf.hasValue()) { 495b39f051631250c49936a475d0e64584afb7f1b93Chet Haase kf.setValue(mProperty.get(target)); 496b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 497b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 498b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 499b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } catch (ClassCastException e) { 500db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase Log.w("PropertyValuesHolder","No such property (" + mProperty.getName() + 501b39f051631250c49936a475d0e64584afb7f1b93Chet Haase ") on target object " + target + ". Trying reflection instead"); 502b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = null; 503b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 504b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 505d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Class targetClass = target.getClass(); 506d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mSetter == null) { 507d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase setupSetter(targetClass); 508d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 509d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase for (Keyframe kf : mKeyframeSet.mKeyframes) { 5107c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (!kf.hasValue()) { 511d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mGetter == null) { 512d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase setupGetter(targetClass); 513db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (mGetter == null) { 514db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Already logged the error - just return to avoid NPE 515db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase return; 516db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 517d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 518d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 5192794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase kf.setValue(mGetter.invoke(target)); 520d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (InvocationTargetException e) { 521d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 522d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (IllegalAccessException e) { 523d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 524d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 525d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 526d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 527d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 528d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 529d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 53021cd1389d2ef218b20994b617c57af120841a57fChet Haase * Utility function to set the value stored in a particular Keyframe. The value used is 53121cd1389d2ef218b20994b617c57af120841a57fChet Haase * whatever the value is for the property name specified in the keyframe on the target object. 53221cd1389d2ef218b20994b617c57af120841a57fChet Haase * 53321cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The target object from which the current value should be extracted. 53421cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param kf The keyframe which holds the property name and value. 53521cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 53621cd1389d2ef218b20994b617c57af120841a57fChet Haase private void setupValue(Object target, Keyframe kf) { 537b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 538b39f051631250c49936a475d0e64584afb7f1b93Chet Haase kf.setValue(mProperty.get(target)); 539b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 54021cd1389d2ef218b20994b617c57af120841a57fChet Haase try { 54121cd1389d2ef218b20994b617c57af120841a57fChet Haase if (mGetter == null) { 54221cd1389d2ef218b20994b617c57af120841a57fChet Haase Class targetClass = target.getClass(); 54321cd1389d2ef218b20994b617c57af120841a57fChet Haase setupGetter(targetClass); 544db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase if (mGetter == null) { 545db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Already logged the error - just return to avoid NPE 546db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase return; 547db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase } 54821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 5492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase kf.setValue(mGetter.invoke(target)); 55021cd1389d2ef218b20994b617c57af120841a57fChet Haase } catch (InvocationTargetException e) { 55121cd1389d2ef218b20994b617c57af120841a57fChet Haase Log.e("PropertyValuesHolder", e.toString()); 55221cd1389d2ef218b20994b617c57af120841a57fChet Haase } catch (IllegalAccessException e) { 55321cd1389d2ef218b20994b617c57af120841a57fChet Haase Log.e("PropertyValuesHolder", e.toString()); 55421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 55521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 55621cd1389d2ef218b20994b617c57af120841a57fChet Haase 55721cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 558a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This function is called by ObjectAnimator when setting the start values for an animation. 55921cd1389d2ef218b20994b617c57af120841a57fChet Haase * The start values are set according to the current values in the target object. The 56021cd1389d2ef218b20994b617c57af120841a57fChet Haase * property whose value is extracted is whatever is specified by the propertyName of this 56121cd1389d2ef218b20994b617c57af120841a57fChet Haase * PropertyValuesHolder object. 56221cd1389d2ef218b20994b617c57af120841a57fChet Haase * 56321cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The object which holds the start values that should be set. 56421cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 56521cd1389d2ef218b20994b617c57af120841a57fChet Haase void setupStartValue(Object target) { 56621cd1389d2ef218b20994b617c57af120841a57fChet Haase setupValue(target, mKeyframeSet.mKeyframes.get(0)); 56721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 56821cd1389d2ef218b20994b617c57af120841a57fChet Haase 56921cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 570a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This function is called by ObjectAnimator when setting the end values for an animation. 57121cd1389d2ef218b20994b617c57af120841a57fChet Haase * The end values are set according to the current values in the target object. The 57221cd1389d2ef218b20994b617c57af120841a57fChet Haase * property whose value is extracted is whatever is specified by the propertyName of this 57321cd1389d2ef218b20994b617c57af120841a57fChet Haase * PropertyValuesHolder object. 57421cd1389d2ef218b20994b617c57af120841a57fChet Haase * 57521cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param target The object which holds the start values that should be set. 57621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 57721cd1389d2ef218b20994b617c57af120841a57fChet Haase void setupEndValue(Object target) { 57821cd1389d2ef218b20994b617c57af120841a57fChet Haase setupValue(target, mKeyframeSet.mKeyframes.get(mKeyframeSet.mKeyframes.size() - 1)); 57921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 58021cd1389d2ef218b20994b617c57af120841a57fChet Haase 58121cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 58221cd1389d2ef218b20994b617c57af120841a57fChet Haase public PropertyValuesHolder clone() { 5837c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 5847c608f25d494c8a0a671e7373efbb47ca635367eChet Haase PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); 5857c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mPropertyName = mPropertyName; 586b39f051631250c49936a475d0e64584afb7f1b93Chet Haase newPVH.mProperty = mProperty; 5877c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mKeyframeSet = mKeyframeSet.clone(); 5887c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mEvaluator = mEvaluator; 5897c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 5907c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (CloneNotSupportedException e) { 5917c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // won't reach here 5927c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return null; 59321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 59421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 5957c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 59621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 597d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Internal function to set the value on the target object, using the setter set up 598a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 599a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 600d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * according to the name of the property. 601d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param target The target object on which the value is set 602d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 603d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void setAnimatedValue(Object target) { 604b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 605b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, getAnimatedValue()); 606b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 607d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mSetter != null) { 608d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase try { 6097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = getAnimatedValue(); 610d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mSetter.invoke(target, mTmpValueArray); 611d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (InvocationTargetException e) { 612d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 613d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } catch (IllegalAccessException e) { 614d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Log.e("PropertyValuesHolder", e.toString()); 615d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 616d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 617d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 618d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 619d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 620a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used 621d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * to calculate animated values. 622d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 623d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase void init() { 624d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase if (mEvaluator == null) { 625b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // We already handle int and float automatically, but not their Object 6267c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // equivalents 6277c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mEvaluator = (mValueType == Integer.class) ? sIntEvaluator : 6287c608f25d494c8a0a671e7373efbb47ca635367eChet Haase (mValueType == Float.class) ? sFloatEvaluator : 6297c608f25d494c8a0a671e7373efbb47ca635367eChet Haase null; 6307c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 6317c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mEvaluator != null) { 6327c608f25d494c8a0a671e7373efbb47ca635367eChet Haase // KeyframeSet knows how to evaluate the common types - only give it a custom 633b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase // evaluator if one has been set on this class 6347c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mKeyframeSet.setEvaluator(mEvaluator); 635d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 636d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 637d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 638d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 639d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * The TypeEvaluator will the automatically determined based on the type of values 640d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * supplied to PropertyValuesHolder. The evaluator can be manually set, however, if so 641d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * desired. This may be important in cases where either the type of the values supplied 642d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * do not match the way that they should be interpolated between, or if the values 643d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * are of a custom type or one not currently understood by the animation system. Currently, 644b2ab04ffb6894f399d5c9ceb15f64eb17b654426Chet Haase * only values of type float and int (and their Object equivalents: Float 645d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. 646d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param evaluator 647d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 6487c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public void setEvaluator(TypeEvaluator evaluator) { 649d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mEvaluator = evaluator; 6507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mKeyframeSet.setEvaluator(evaluator); 651d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 652d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 653d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 654d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Function used to calculate the value according to the evaluator set up for 655a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). 656d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 657d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param fraction The elapsed, interpolated fraction of the animation. 658d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 6597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 6607c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mAnimatedValue = mKeyframeSet.getValue(fraction); 661d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 662d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 663d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 664d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Sets the name of the property that will be animated. This name is used to derive 665d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a setter function that will be called to set animated values. 666d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * For example, a property name of <code>foo</code> will result 667d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * in a call to the function <code>setFoo()</code> on the target object. If either 668d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will 669d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * also be derived and called. 670d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 671d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <p>Note that the setter function derived from this property name 672d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * must take the same parameter type as the 673d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to 674d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * the setter function will fail.</p> 675d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * 676d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @param propertyName The name of the property being animated. 677d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 678d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase public void setPropertyName(String propertyName) { 679d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase mPropertyName = propertyName; 680d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 681d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 682d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 683b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * Sets the property that will be animated. 684b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 685b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * <p>Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property 686b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * must exist on the target object specified in that ObjectAnimator.</p> 687b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * 688b39f051631250c49936a475d0e64584afb7f1b93Chet Haase * @param property The property being animated. 689b39f051631250c49936a475d0e64584afb7f1b93Chet Haase */ 690b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public void setProperty(Property property) { 691b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty = property; 692b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 693b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 694b39f051631250c49936a475d0e64584afb7f1b93Chet Haase /** 695d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * Gets the name of the property that will be animated. This name will be used to derive 696d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * a setter function that will be called to set animated values. 697d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * For example, a property name of <code>foo</code> will result 698d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * in a call to the function <code>setFoo()</code> on the target object. If either 699d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will 700d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * also be derived and called. 701d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 702d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase public String getPropertyName() { 703d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return mPropertyName; 704d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 705d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase 706d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase /** 707a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value 708d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * most recently calculated in calculateValue(). 709d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase * @return 710d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase */ 711d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase Object getAnimatedValue() { 712d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase return mAnimatedValue; 713d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase } 7147c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 715e9140a72b1059574046a624b471b2c3a35806496Chet Haase @Override 716e9140a72b1059574046a624b471b2c3a35806496Chet Haase public String toString() { 717e9140a72b1059574046a624b471b2c3a35806496Chet Haase return mPropertyName + ": " + mKeyframeSet.toString(); 718e9140a72b1059574046a624b471b2c3a35806496Chet Haase } 719e9140a72b1059574046a624b471b2c3a35806496Chet Haase 7206e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase /** 7216e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * Utility method to derive a setter/getter method name from a property name, where the 7226e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * prefix is typically "set" or "get" and the first letter of the property name is 7236e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * capitalized. 7246e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * 7256e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @param prefix The precursor to the method name, before the property name begins, typically 7266e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * "set" or "get". 7276e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @param propertyName The name of the property that represents the bulk of the method name 7286e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * after the prefix. The first letter of this word will be capitalized in the resulting 7296e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * method name. 7306e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * @return String the property name converted to a method name according to the conventions 7316e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase * specified above. 7326e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase */ 7336e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase static String getMethodName(String prefix, String propertyName) { 734b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (propertyName == null || propertyName.length() == 0) { 735b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // shouldn't get here 736b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return prefix; 737b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 738b39f051631250c49936a475d0e64584afb7f1b93Chet Haase char firstLetter = Character.toUpperCase(propertyName.charAt(0)); 7396e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String theRest = propertyName.substring(1); 7406e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return prefix + firstLetter + theRest; 7416e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 7426e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 7437c608f25d494c8a0a671e7373efbb47ca635367eChet Haase static class IntPropertyValuesHolder extends PropertyValuesHolder { 7447c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 745b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // Cache JNI functions to avoid looking them up twice 7466e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = 7476e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase new HashMap<Class, HashMap<String, Integer>>(); 7486e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase int mJniSetter; 749b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private IntProperty mIntProperty; 7506e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 7517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase IntKeyframeSet mIntKeyframeSet; 7527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int mIntAnimatedValue; 7537c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 7547c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) { 7557c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 7567c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mValueType = int.class; 7577c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mKeyframeSet = keyframeSet; 7587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; 7597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 7607c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 761b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) { 762b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 763b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mValueType = int.class; 764b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mKeyframeSet = keyframeSet; 765b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; 766b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof IntProperty) { 767b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty = (IntProperty) mProperty; 768b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 769b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 770b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 7717c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public IntPropertyValuesHolder(String propertyName, int... values) { 7727c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 7737c608f25d494c8a0a671e7373efbb47ca635367eChet Haase setIntValues(values); 774691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase } 775691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase 776b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public IntPropertyValuesHolder(Property property, int... values) { 777b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 778b39f051631250c49936a475d0e64584afb7f1b93Chet Haase setIntValues(values); 779b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof IntProperty) { 780b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty = (IntProperty) mProperty; 781b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 782b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 783b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 784691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase @Override 785691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase public void setIntValues(int... values) { 786691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase super.setIntValues(values); 7877c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; 7887c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 7897c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 7907c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 7917c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 7927c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mIntAnimatedValue = mIntKeyframeSet.getIntValue(fraction); 7937c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 7947c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 7957c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 7967c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Object getAnimatedValue() { 7977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return mIntAnimatedValue; 7987c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 7997c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 8007c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 8017c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public IntPropertyValuesHolder clone() { 8027c608f25d494c8a0a671e7373efbb47ca635367eChet Haase IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone(); 8037c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mIntKeyframeSet = (IntKeyframeSet) newPVH.mKeyframeSet; 8047c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 8057c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8067c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 8077c608f25d494c8a0a671e7373efbb47ca635367eChet Haase /** 8087c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * Internal function to set the value on the target object, using the setter set up 8097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 8107c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 8117c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * according to the name of the property. 8127c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * @param target The target object on which the value is set 8137c608f25d494c8a0a671e7373efbb47ca635367eChet Haase */ 8147c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 8157c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void setAnimatedValue(Object target) { 816b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mIntProperty != null) { 817b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mIntProperty.setValue(target, mIntAnimatedValue); 818b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 819b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 820b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 821b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, mIntAnimatedValue); 822b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 823b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 8246e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 8256e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase nCallIntMethod(target, mJniSetter, mIntAnimatedValue); 8266e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return; 8276e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8287c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mSetter != null) { 8297c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 8307c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = mIntAnimatedValue; 8317c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mSetter.invoke(target, mTmpValueArray); 8327c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (InvocationTargetException e) { 8337c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 8347c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (IllegalAccessException e) { 8357c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 8367c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8377c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8387c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8396e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 8406e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase @Override 8416e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 842b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 843b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 844b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 8456e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Check new static hashmap<propName, int> for setter method 8466e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase try { 8476e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().lock(); 8486e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass); 8496e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap != null) { 8506e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase Integer mJniSetterInteger = propertyMap.get(mPropertyName); 8516e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetterInteger != null) { 8526e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mJniSetter = mJniSetterInteger; 8536e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8546e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8556e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 8566e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName("set", mPropertyName); 8576e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mJniSetter = nGetIntMethod(targetClass, methodName); 8586e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 8596e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap == null) { 8606e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase propertyMap = new HashMap<String, Integer>(); 8616e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase sJNISetterPropertyMap.put(targetClass, propertyMap); 8626e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8636e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase propertyMap.put(mPropertyName, mJniSetter); 8646e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8656e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8666e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } catch (NoSuchMethodError e) { 867db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Couldn't find it via JNI - try reflection next. Probably means the method 868db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // doesn't exist, or the type is wrong. An error will be logged later if 869db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // reflection fails as well. 8706e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } finally { 8716e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().unlock(); 8726e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8736e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 8746e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Couldn't find method through fast JNI approach - just use reflection 8756e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase super.setupSetter(targetClass); 8766e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8776e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 8787c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8797c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 8807c608f25d494c8a0a671e7373efbb47ca635367eChet Haase static class FloatPropertyValuesHolder extends PropertyValuesHolder { 8817c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 882b39f051631250c49936a475d0e64584afb7f1b93Chet Haase // Cache JNI functions to avoid looking them up twice 8836e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = 8846e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase new HashMap<Class, HashMap<String, Integer>>(); 8856e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase int mJniSetter; 886b39f051631250c49936a475d0e64584afb7f1b93Chet Haase private FloatProperty mFloatProperty; 8876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 8887c608f25d494c8a0a671e7373efbb47ca635367eChet Haase FloatKeyframeSet mFloatKeyframeSet; 8897c608f25d494c8a0a671e7373efbb47ca635367eChet Haase float mFloatAnimatedValue; 8907c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 8917c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) { 8927c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 8937c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mValueType = float.class; 8947c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mKeyframeSet = keyframeSet; 8957c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; 8967c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 8977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 898b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) { 899b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 900b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mValueType = float.class; 901b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mKeyframeSet = keyframeSet; 902b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; 903b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof FloatProperty) { 904b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty = (FloatProperty) mProperty; 905b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 906b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 907b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 9087c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public FloatPropertyValuesHolder(String propertyName, float... values) { 9097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase super(propertyName); 9107c608f25d494c8a0a671e7373efbb47ca635367eChet Haase setFloatValues(values); 911691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase } 912691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase 913b39f051631250c49936a475d0e64584afb7f1b93Chet Haase public FloatPropertyValuesHolder(Property property, float... values) { 914b39f051631250c49936a475d0e64584afb7f1b93Chet Haase super(property); 915b39f051631250c49936a475d0e64584afb7f1b93Chet Haase setFloatValues(values); 916b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (property instanceof FloatProperty) { 917b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty = (FloatProperty) mProperty; 918b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 919b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 920b39f051631250c49936a475d0e64584afb7f1b93Chet Haase 921691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase @Override 922691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase public void setFloatValues(float... values) { 923691ac26817d489d9770aa6ba7b098ff17e8be99aChet Haase super.setFloatValues(values); 9247c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; 9257c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9267c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 9277c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 9287c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void calculateValue(float fraction) { 9297c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mFloatAnimatedValue = mFloatKeyframeSet.getFloatValue(fraction); 9307c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9317c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 9327c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 9337c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Object getAnimatedValue() { 9347c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return mFloatAnimatedValue; 9357c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9367c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 9377c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 9387c608f25d494c8a0a671e7373efbb47ca635367eChet Haase public FloatPropertyValuesHolder clone() { 9397c608f25d494c8a0a671e7373efbb47ca635367eChet Haase FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone(); 9407c608f25d494c8a0a671e7373efbb47ca635367eChet Haase newPVH.mFloatKeyframeSet = (FloatKeyframeSet) newPVH.mKeyframeSet; 9417c608f25d494c8a0a671e7373efbb47ca635367eChet Haase return newPVH; 9427c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9437c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 9447c608f25d494c8a0a671e7373efbb47ca635367eChet Haase /** 9457c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * Internal function to set the value on the target object, using the setter set up 9467c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator 9477c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * to handle turning the value calculated by ValueAnimator into a value set on the object 9487c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * according to the name of the property. 9497c608f25d494c8a0a671e7373efbb47ca635367eChet Haase * @param target The target object on which the value is set 9507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase */ 9517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase @Override 9527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase void setAnimatedValue(Object target) { 953b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mFloatProperty != null) { 954b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mFloatProperty.setValue(target, mFloatAnimatedValue); 955b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 956b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 957b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 958b39f051631250c49936a475d0e64584afb7f1b93Chet Haase mProperty.set(target, mFloatAnimatedValue); 959b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 960b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 9616e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 9626e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue); 9636e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase return; 9646e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 9657c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (mSetter != null) { 9667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase try { 9677c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mTmpValueArray[0] = mFloatAnimatedValue; 9687c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mSetter.invoke(target, mTmpValueArray); 9697c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (InvocationTargetException e) { 9707c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 9717c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } catch (IllegalAccessException e) { 9727c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Log.e("PropertyValuesHolder", e.toString()); 9737c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9747c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9757c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 9767c608f25d494c8a0a671e7373efbb47ca635367eChet Haase 9776e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase @Override 9786e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void setupSetter(Class targetClass) { 979b39f051631250c49936a475d0e64584afb7f1b93Chet Haase if (mProperty != null) { 980b39f051631250c49936a475d0e64584afb7f1b93Chet Haase return; 981b39f051631250c49936a475d0e64584afb7f1b93Chet Haase } 9826e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Check new static hashmap<propName, int> for setter method 9836e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase try { 9846e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().lock(); 9856e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass); 9866e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap != null) { 9876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase Integer mJniSetterInteger = propertyMap.get(mPropertyName); 9886e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetterInteger != null) { 9896e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mJniSetter = mJniSetterInteger; 9906e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 9916e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 9926e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 9936e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase String methodName = getMethodName("set", mPropertyName); 9946e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mJniSetter = nGetFloatMethod(targetClass, methodName); 9956e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter != 0) { 9966e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (propertyMap == null) { 9976e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase propertyMap = new HashMap<String, Integer>(); 9986e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase sJNISetterPropertyMap.put(targetClass, propertyMap); 9996e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10006e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase propertyMap.put(mPropertyName, mJniSetter); 10016e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10026e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10036e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } catch (NoSuchMethodError e) { 1004db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // Couldn't find it via JNI - try reflection next. Probably means the method 1005db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // doesn't exist, or the type is wrong. An error will be logged later if 1006db4101c7d5a2af174bdc61dc706329faabaeb5c6Chet Haase // reflection fails as well. 10076e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } finally { 10086e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase mPropertyMapLock.writeLock().unlock(); 10096e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10106e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase if (mJniSetter == 0) { 10116e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase // Couldn't find method through fast JNI approach - just use reflection 10126e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase super.setupSetter(targetClass); 10136e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10146e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase } 10156e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 10167c608f25d494c8a0a671e7373efbb47ca635367eChet Haase } 10176e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase 10186e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase native static private int nGetIntMethod(Class targetClass, String methodName); 10196e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase native static private int nGetFloatMethod(Class targetClass, String methodName); 10206e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase native static private void nCallIntMethod(Object target, int methodID, int arg); 10216e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase native static private void nCallFloatMethod(Object target, int methodID, float arg); 1022d953d08e9299072130d9f4411cbcf6678bbce822Chet Haase}