diff options
author | Chet Haase <chet@google.com> | 2011-06-08 12:51:06 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-06-08 12:51:06 -0700 |
commit | b19fcf3e9c6b9c8c2885b9ac7f7f836a0e2d6d22 (patch) | |
tree | e4eaf3e1713caf35bdaca546416453ba02ff8835 /core | |
parent | 608a23a07e6b9f7690e3dea0fff87408c6836308 (diff) | |
parent | b39f051631250c49936a475d0e64584afb7f1b93 (diff) | |
download | frameworks_base-b19fcf3e9c6b9c8c2885b9ac7f7f836a0e2d6d22.zip frameworks_base-b19fcf3e9c6b9c8c2885b9ac7f7f836a0e2d6d22.tar.gz frameworks_base-b19fcf3e9c6b9c8c2885b9ac7f7f836a0e2d6d22.tar.bz2 |
Merge "Add 'Property' object"
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/animation/FloatEvaluator.java | 8 | ||||
-rw-r--r-- | core/java/android/animation/IntEvaluator.java | 8 | ||||
-rw-r--r-- | core/java/android/animation/ObjectAnimator.java | 221 | ||||
-rw-r--r-- | core/java/android/animation/PropertyValuesHolder.java | 213 | ||||
-rw-r--r-- | core/java/android/animation/TypeEvaluator.java | 4 | ||||
-rw-r--r-- | core/java/android/util/FloatProperty.java | 48 | ||||
-rw-r--r-- | core/java/android/util/IntProperty.java | 48 | ||||
-rw-r--r-- | core/java/android/util/NoSuchPropertyException.java | 30 | ||||
-rw-r--r-- | core/java/android/util/Property.java | 106 | ||||
-rw-r--r-- | core/java/android/util/ReflectiveProperty.java | 163 | ||||
-rw-r--r-- | core/java/android/view/GLES20RecordingCanvas.java | 4 | ||||
-rw-r--r-- | core/java/android/view/View.java | 165 |
12 files changed, 925 insertions, 93 deletions
diff --git a/core/java/android/animation/FloatEvaluator.java b/core/java/android/animation/FloatEvaluator.java index 9e2054d..9463aa1 100644 --- a/core/java/android/animation/FloatEvaluator.java +++ b/core/java/android/animation/FloatEvaluator.java @@ -19,7 +19,7 @@ package android.animation; /** * This evaluator can be used to perform type interpolation between <code>float</code> values. */ -public class FloatEvaluator implements TypeEvaluator { +public class FloatEvaluator implements TypeEvaluator<Number> { /** * This function returns the result of linearly interpolating the start and end values, with @@ -35,8 +35,8 @@ public class FloatEvaluator implements TypeEvaluator { * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ - public Object evaluate(float fraction, Object startValue, Object endValue) { - float startFloat = ((Number) startValue).floatValue(); - return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); + public Float evaluate(float fraction, Number startValue, Number endValue) { + float startFloat = startValue.floatValue(); + return startFloat + fraction * (endValue.floatValue() - startFloat); } }
\ No newline at end of file diff --git a/core/java/android/animation/IntEvaluator.java b/core/java/android/animation/IntEvaluator.java index 7288927..34fb0dc 100644 --- a/core/java/android/animation/IntEvaluator.java +++ b/core/java/android/animation/IntEvaluator.java @@ -19,7 +19,7 @@ package android.animation; /** * This evaluator can be used to perform type interpolation between <code>int</code> values. */ -public class IntEvaluator implements TypeEvaluator { +public class IntEvaluator implements TypeEvaluator<Integer> { /** * This function returns the result of linearly interpolating the start and end values, with @@ -35,8 +35,8 @@ public class IntEvaluator implements TypeEvaluator { * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ - public Object evaluate(float fraction, Object startValue, Object endValue) { - int startInt = ((Number) startValue).intValue(); - return (int) (startInt + fraction * (((Number) endValue).intValue() - startInt)); + public Integer evaluate(float fraction, Integer startValue, Integer endValue) { + int startInt = startValue; + return (int)(startInt + fraction * (endValue - startInt)); } }
\ No newline at end of file diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index b8a7cb2..31c5f8d 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -17,6 +17,7 @@ package android.animation; import android.util.Log; +import android.util.Property; import java.lang.reflect.Method; import java.util.ArrayList; @@ -39,6 +40,8 @@ public final class ObjectAnimator extends ValueAnimator { private String mPropertyName; + private Property mProperty; + /** * Sets the name of the property that will be animated. This name is used to derive * a setter function that will be called to set animated values. @@ -63,7 +66,7 @@ public final class ObjectAnimator extends ValueAnimator { * using more than one PropertyValuesHolder objects, then setting the propertyName simply * sets the propertyName in the first of those PropertyValuesHolder objects.</p> * - * @param propertyName The name of the property being animated. + * @param propertyName The name of the property being animated. Should not be null. */ public void setPropertyName(String propertyName) { // mValues could be null if this is being constructed piecemeal. Just record the @@ -81,6 +84,31 @@ public final class ObjectAnimator extends ValueAnimator { } /** + * Sets the property that will be animated. Property objects will take precedence over + * properties specified by the {@link #setPropertyName(String)} method. Animations should + * be set up to use one or the other, not both. + * + * @param property The property being animated. Should not be null. + */ + public void setProperty(Property property) { + // mValues could be null if this is being constructed piecemeal. Just record the + // propertyName to be used later when setValues() is called if so. + if (mValues != null) { + PropertyValuesHolder valuesHolder = mValues[0]; + String oldName = valuesHolder.getPropertyName(); + valuesHolder.setProperty(property); + mValuesMap.remove(oldName); + mValuesMap.put(mPropertyName, valuesHolder); + } + if (mProperty != null) { + mPropertyName = property.getName(); + } + mProperty = property; + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** * Gets the name of the property that will be animated. This name will be used to derive * a setter function that will be called to set animated values. * For example, a property name of <code>foo</code> will result @@ -93,36 +121,6 @@ public final class ObjectAnimator extends ValueAnimator { } /** - * Determine the setter or getter function using the JavaBeans convention of setFoo or - * getFoo for a property named 'foo'. This function figures out what the name of the - * function should be and uses reflection to find the Method with that name on the - * target object. - * - * @param prefix "set" or "get", depending on whether we need a setter or getter. - * @return Method the method associated with mPropertyName. - */ - private Method getPropertyFunction(String prefix, Class valueType) { - // TODO: faster implementation... - Method returnVal = null; - String firstLetter = mPropertyName.substring(0, 1); - String theRest = mPropertyName.substring(1); - firstLetter = firstLetter.toUpperCase(); - String setterName = prefix + firstLetter + theRest; - Class args[] = null; - if (valueType != null) { - args = new Class[1]; - args[0] = valueType; - } - try { - returnVal = mTarget.getClass().getMethod(setterName, args); - } catch (NoSuchMethodException e) { - Log.e("ObjectAnimator", - "Couldn't find setter/getter for property " + mPropertyName + ": " + e); - } - return returnVal; - } - - /** * Creates a new ObjectAnimator object. This default constructor is primarily for * use internally; the other constructors which take parameters are more generally * useful. @@ -131,8 +129,8 @@ public final class ObjectAnimator extends ValueAnimator { } /** - * A constructor that takes a single property name and set of values. This constructor is - * used in the simple case of animating a single property. + * Private utility constructor that initializes the target object and name of the + * property being animated. * * @param target The object whose property is to be animated. This object should * have a public method on it called <code>setName()</code>, where <code>name</code> is @@ -145,19 +143,29 @@ public final class ObjectAnimator extends ValueAnimator { } /** + * Private utility constructor that initializes the target object and property being animated. + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + */ + private <T> ObjectAnimator(T target, Property<T, ?> property) { + mTarget = target; + setProperty(property); + } + + /** * Constructs and returns an ObjectAnimator that animates between int values. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). * * @param target The object whose property is to be animated. This object should * have a public method on it called <code>setName()</code>, where <code>name</code> is * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. * @param values A set of values that the animation will animate between over time. - * @return A ValueAnimator object that is set up to animate between the given values. + * @return An ObjectAnimator object that is set up to animate between the given values. */ public static ObjectAnimator ofInt(Object target, String propertyName, int... values) { ObjectAnimator anim = new ObjectAnimator(target, propertyName); @@ -166,19 +174,36 @@ public final class ObjectAnimator extends ValueAnimator { } /** + * Constructs and returns an ObjectAnimator that animates between int values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> property, int... values) { + ObjectAnimator anim = new ObjectAnimator(target, property); + anim.setIntValues(values); + return anim; + } + + /** * Constructs and returns an ObjectAnimator that animates between float values. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). * * @param target The object whose property is to be animated. This object should * have a public method on it called <code>setName()</code>, where <code>name</code> is * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. * @param values A set of values that the animation will animate between over time. - * @return A ValueAnimator object that is set up to animate between the given values. + * @return An ObjectAnimator object that is set up to animate between the given values. */ public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { ObjectAnimator anim = new ObjectAnimator(target, propertyName); @@ -187,21 +212,40 @@ public final class ObjectAnimator extends ValueAnimator { } /** - * A constructor that takes <code>PropertyValueHolder</code> values. This constructor should - * be used when animating several properties at once with the same ObjectAnimator, since - * PropertyValuesHolder allows you to associate a set of animation values with a property - * name. + * Constructs and returns an ObjectAnimator that animates between float values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property, + float... values) { + ObjectAnimator anim = new ObjectAnimator(target, property); + anim.setFloatValues(values); + return anim; + } + + /** + * Constructs and returns an ObjectAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). * * @param target The object whose property is to be animated. This object should - * have public methods on it called <code>setName()</code>, where <code>name</code> is - * the name of the property passed in as the <code>propertyName</code> parameter for - * each of the PropertyValuesHolder objects. + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the ncessry interpolation between the Object values to derive the animated + * provide the necessary interpolation between the Object values to derive the animated * value. - * @param values The PropertyValuesHolder objects which hold each the property name and values - * to animate that property between. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. */ public static ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values) { @@ -212,19 +256,44 @@ public final class ObjectAnimator extends ValueAnimator { } /** - * Constructs and returns an ObjectAnimator that animates between the sets of values - * specifed in <code>PropertyValueHolder</code> objects. This variant should - * be used when animating several properties at once with the same ObjectAnimator, since - * PropertyValuesHolder allows you to associate a set of animation values with a property - * name. + * Constructs and returns an ObjectAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). * - * @param target The object whose property is to be animated. This object should - * have public methods on it called <code>setName()</code>, where <code>name</code> is - * the name of the property passed in as the <code>propertyName</code> parameter for - * each of the PropertyValuesHolder objects. - * @param values A set of PropertyValuesHolder objects whose values will be animated - * between over time. - * @return A ValueAnimator object that is set up to animate between the given values. + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property, + TypeEvaluator<V> evaluator, V... values) { + ObjectAnimator anim = new ObjectAnimator(target, property); + anim.setObjectValues(values); + anim.setEvaluator(evaluator); + return anim; + } + + /** + * Constructs and returns an ObjectAnimator that animates between the sets of values specified + * in <code>PropertyValueHolder</code> objects. This variant should be used when animating + * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows + * you to associate a set of animation values with a property name. + * + * @param target The object whose property is to be animated. Depending on how the + * PropertyValuesObjects were constructed, the target object should either have the {@link + * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the + * PropertyValuesHOlder objects were created with property names) the target object should have + * public methods on it called <code>setName()</code>, where <code>name</code> is the name of + * the property passed in as the <code>propertyName</code> parameter for each of the + * PropertyValuesHolder objects. + * @param values A set of PropertyValuesHolder objects whose values will be animated between + * over time. + * @return An ObjectAnimator object that is set up to animate between the given values. */ public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) { @@ -239,7 +308,11 @@ public final class ObjectAnimator extends ValueAnimator { if (mValues == null || mValues.length == 0) { // No values yet - this animator is being constructed piecemeal. Init the values with // whatever the current propertyName is - setValues(PropertyValuesHolder.ofInt(mPropertyName, values)); + if (mProperty != null) { + setValues(PropertyValuesHolder.ofInt(mProperty, values)); + } else { + setValues(PropertyValuesHolder.ofInt(mPropertyName, values)); + } } else { super.setIntValues(values); } @@ -250,7 +323,11 @@ public final class ObjectAnimator extends ValueAnimator { if (mValues == null || mValues.length == 0) { // No values yet - this animator is being constructed piecemeal. Init the values with // whatever the current propertyName is - setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); + if (mProperty != null) { + setValues(PropertyValuesHolder.ofFloat(mProperty, values)); + } else { + setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); + } } else { super.setFloatValues(values); } @@ -261,7 +338,11 @@ public final class ObjectAnimator extends ValueAnimator { if (mValues == null || mValues.length == 0) { // No values yet - this animator is being constructed piecemeal. Init the values with // whatever the current propertyName is - setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values)); + if (mProperty != null) { + setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator)null, values)); + } else { + setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values)); + } } else { super.setObjectValues(values); } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 6f91fc0..58f23f7 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -16,7 +16,10 @@ package android.animation; +import android.util.FloatProperty; +import android.util.IntProperty; import android.util.Log; +import android.util.Property; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -39,6 +42,11 @@ public class PropertyValuesHolder implements Cloneable { String mPropertyName; /** + * @hide + */ + protected Property mProperty; + + /** * The setter function, if needed. ObjectAnimator hands off this functionality to * PropertyValuesHolder, since it holds all of the per-property information. This * property is automatically @@ -124,6 +132,17 @@ public class PropertyValuesHolder implements Cloneable { } /** + * Internal utility constructor, used by the factory methods to set the property. + * @param property The property for this holder. + */ + private PropertyValuesHolder(Property property) { + mProperty = property; + if (property != null) { + mPropertyName = property.getName(); + } + } + + /** * Constructs and returns a PropertyValuesHolder with a given property name and * set of int values. * @param propertyName The name of the property being animated. @@ -131,8 +150,18 @@ public class PropertyValuesHolder implements Cloneable { * @return PropertyValuesHolder The constructed PropertyValuesHolder object. */ public static PropertyValuesHolder ofInt(String propertyName, int... values) { - PropertyValuesHolder pvh = new IntPropertyValuesHolder(propertyName, values); - return pvh; + return new IntPropertyValuesHolder(propertyName, values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of int values. + * @param property The property being animated. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values) { + return new IntPropertyValuesHolder(property, values); } /** @@ -143,18 +172,28 @@ public class PropertyValuesHolder implements Cloneable { * @return PropertyValuesHolder The constructed PropertyValuesHolder object. */ public static PropertyValuesHolder ofFloat(String propertyName, float... values) { - PropertyValuesHolder pvh = new FloatPropertyValuesHolder(propertyName, values); - return pvh; + return new FloatPropertyValuesHolder(propertyName, values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of float values. + * @param property The property being animated. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) { + return new FloatPropertyValuesHolder(property, values); } /** * Constructs and returns a PropertyValuesHolder with a given property name and * set of Object values. This variant also takes a TypeEvaluator because the system - * cannot interpolate between objects of unknown type. + * cannot automatically interpolate between objects of unknown type. * * @param propertyName The name of the property being animated. * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the ncessry interpolation between the Object values to derive the animated + * provide the necessary interpolation between the Object values to derive the animated * value. * @param values The values that the named property will animate between. * @return PropertyValuesHolder The constructed PropertyValuesHolder object. @@ -168,6 +207,26 @@ public class PropertyValuesHolder implements Cloneable { } /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of Object values. This variant also takes a TypeEvaluator because the system + * cannot automatically interpolate between objects of unknown type. + * + * @param property The property being animated. Should not be null. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static <V> PropertyValuesHolder ofObject(Property property, + TypeEvaluator<V> evaluator, V... values) { + PropertyValuesHolder pvh = new PropertyValuesHolder(property); + pvh.setObjectValues(values); + pvh.setEvaluator(evaluator); + return pvh; + } + + /** * Constructs and returns a PropertyValuesHolder object with the specified property name and set * of values. These values can be of any type, but the type should be consistent so that * an appropriate {@link android.animation.TypeEvaluator} can be found that matches @@ -202,6 +261,37 @@ public class PropertyValuesHolder implements Cloneable { } /** + * Constructs and returns a PropertyValuesHolder object with the specified property and set + * of values. These values can be of any type, but the type should be consistent so that + * an appropriate {@link android.animation.TypeEvaluator} can be found that matches + * the common type. + * <p>If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling the property's + * {@link android.util.Property#get(Object)} function. + * Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction with + * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * @param property The property associated with this set of values. Should not be null. + * @param values The set of values to animate between. + */ + public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { + KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); + if (keyframeSet instanceof IntKeyframeSet) { + return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet); + } else if (keyframeSet instanceof FloatKeyframeSet) { + return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet); + } + else { + PropertyValuesHolder pvh = new PropertyValuesHolder(property); + pvh.mKeyframeSet = keyframeSet; + pvh.mValueType = ((Keyframe)values[0]).getType(); + return pvh; + } + } + + /** * Set the animated values for this object to this set of ints. * If there is only one value, it is assumed to be the end value of an animation, * and an initial value will be derived, if possible, by calling a getter function @@ -349,7 +439,6 @@ public class PropertyValuesHolder implements Cloneable { // Have to lock property map prior to reading it, to guard against // another thread putting something in there after we've checked it // but before we've added an entry to it - // TODO: can we store the setter/getter per Class instead of per Object? mPropertyMapLock.writeLock().lock(); HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass); if (propertyMap != null) { @@ -395,6 +484,22 @@ public class PropertyValuesHolder implements Cloneable { * @param target The object on which the setter (and possibly getter) exist. */ void setupSetterAndGetter(Object target) { + if (mProperty != null) { + // check to make sure that mProperty is on the class of target + try { + Object testValue = mProperty.get(target); + for (Keyframe kf : mKeyframeSet.mKeyframes) { + if (!kf.hasValue()) { + kf.setValue(mProperty.get(target)); + } + } + return; + } catch (ClassCastException e) { + Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() + + ") on target object " + target + ". Trying reflection instead"); + mProperty = null; + } + } Class targetClass = target.getClass(); if (mSetter == null) { setupSetter(targetClass); @@ -423,6 +528,9 @@ public class PropertyValuesHolder implements Cloneable { * @param kf The keyframe which holds the property name and value. */ private void setupValue(Object target, Keyframe kf) { + if (mProperty != null) { + kf.setValue(mProperty.get(target)); + } try { if (mGetter == null) { Class targetClass = target.getClass(); @@ -465,6 +573,7 @@ public class PropertyValuesHolder implements Cloneable { try { PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); newPVH.mPropertyName = mPropertyName; + newPVH.mProperty = mProperty; newPVH.mKeyframeSet = mKeyframeSet.clone(); newPVH.mEvaluator = mEvaluator; return newPVH; @@ -482,6 +591,9 @@ public class PropertyValuesHolder implements Cloneable { * @param target The target object on which the value is set */ void setAnimatedValue(Object target) { + if (mProperty != null) { + mProperty.set(target, getAnimatedValue()); + } if (mSetter != null) { try { mTmpValueArray[0] = getAnimatedValue(); @@ -558,6 +670,18 @@ public class PropertyValuesHolder implements Cloneable { } /** + * Sets the property that will be animated. + * + * <p>Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property + * must exist on the target object specified in that ObjectAnimator.</p> + * + * @param property The property being animated. + */ + public void setProperty(Property property) { + mProperty = property; + } + + /** * Gets the name of the property that will be animated. This name will be used to derive * a setter function that will be called to set animated values. * For example, a property name of <code>foo</code> will result @@ -597,17 +721,22 @@ public class PropertyValuesHolder implements Cloneable { * specified above. */ static String getMethodName(String prefix, String propertyName) { - char firstLetter = propertyName.charAt(0); + if (propertyName == null || propertyName.length() == 0) { + // shouldn't get here + return prefix; + } + char firstLetter = Character.toUpperCase(propertyName.charAt(0)); String theRest = propertyName.substring(1); - firstLetter = Character.toUpperCase(firstLetter); return prefix + firstLetter + theRest; } static class IntPropertyValuesHolder extends PropertyValuesHolder { + // Cache JNI functions to avoid looking them up twice private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = new HashMap<Class, HashMap<String, Integer>>(); int mJniSetter; + private IntProperty mIntProperty; IntKeyframeSet mIntKeyframeSet; int mIntAnimatedValue; @@ -619,11 +748,29 @@ public class PropertyValuesHolder implements Cloneable { mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; } + public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) { + super(property); + mValueType = int.class; + mKeyframeSet = keyframeSet; + mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + if (property instanceof IntProperty) { + mIntProperty = (IntProperty) mProperty; + } + } + public IntPropertyValuesHolder(String propertyName, int... values) { super(propertyName); setIntValues(values); } + public IntPropertyValuesHolder(Property property, int... values) { + super(property); + setIntValues(values); + if (property instanceof IntProperty) { + mIntProperty = (IntProperty) mProperty; + } + } + @Override public void setIntValues(int... values) { super.setIntValues(values); @@ -656,6 +803,14 @@ public class PropertyValuesHolder implements Cloneable { */ @Override void setAnimatedValue(Object target) { + if (mIntProperty != null) { + mIntProperty.setValue(target, mIntAnimatedValue); + return; + } + if (mProperty != null) { + mProperty.set(target, mIntAnimatedValue); + return; + } if (mJniSetter != 0) { nCallIntMethod(target, mJniSetter, mIntAnimatedValue); return; @@ -674,6 +829,9 @@ public class PropertyValuesHolder implements Cloneable { @Override void setupSetter(Class targetClass) { + if (mProperty != null) { + return; + } // Check new static hashmap<propName, int> for setter method try { mPropertyMapLock.writeLock().lock(); @@ -696,7 +854,8 @@ public class PropertyValuesHolder implements Cloneable { } } } catch (NoSuchMethodError e) { - // System.out.println("Can't find native method using JNI, use reflection" + e); + Log.d("PropertyValuesHolder", + "Can't find native method using JNI, use reflection" + e); } finally { mPropertyMapLock.writeLock().unlock(); } @@ -709,9 +868,11 @@ public class PropertyValuesHolder implements Cloneable { static class FloatPropertyValuesHolder extends PropertyValuesHolder { + // Cache JNI functions to avoid looking them up twice private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = new HashMap<Class, HashMap<String, Integer>>(); int mJniSetter; + private FloatProperty mFloatProperty; FloatKeyframeSet mFloatKeyframeSet; float mFloatAnimatedValue; @@ -723,11 +884,29 @@ public class PropertyValuesHolder implements Cloneable { mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; } + public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) { + super(property); + mValueType = float.class; + mKeyframeSet = keyframeSet; + mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + if (property instanceof FloatProperty) { + mFloatProperty = (FloatProperty) mProperty; + } + } + public FloatPropertyValuesHolder(String propertyName, float... values) { super(propertyName); setFloatValues(values); } + public FloatPropertyValuesHolder(Property property, float... values) { + super(property); + setFloatValues(values); + if (property instanceof FloatProperty) { + mFloatProperty = (FloatProperty) mProperty; + } + } + @Override public void setFloatValues(float... values) { super.setFloatValues(values); @@ -760,6 +939,14 @@ public class PropertyValuesHolder implements Cloneable { */ @Override void setAnimatedValue(Object target) { + if (mFloatProperty != null) { + mFloatProperty.setValue(target, mFloatAnimatedValue); + return; + } + if (mProperty != null) { + mProperty.set(target, mFloatAnimatedValue); + return; + } if (mJniSetter != 0) { nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue); return; @@ -778,6 +965,9 @@ public class PropertyValuesHolder implements Cloneable { @Override void setupSetter(Class targetClass) { + if (mProperty != null) { + return; + } // Check new static hashmap<propName, int> for setter method try { mPropertyMapLock.writeLock().lock(); @@ -800,7 +990,8 @@ public class PropertyValuesHolder implements Cloneable { } } } catch (NoSuchMethodError e) { - // System.out.println("Can't find native method using JNI, use reflection" + e); + Log.d("PropertyValuesHolder", + "Can't find native method using JNI, use reflection" + e); } finally { mPropertyMapLock.writeLock().unlock(); } diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java index fa49175..e738da1 100644 --- a/core/java/android/animation/TypeEvaluator.java +++ b/core/java/android/animation/TypeEvaluator.java @@ -24,7 +24,7 @@ package android.animation; * * @see ValueAnimator#setEvaluator(TypeEvaluator) */ -public interface TypeEvaluator { +public interface TypeEvaluator<T> { /** * This function returns the result of linearly interpolating the start and end values, with @@ -39,6 +39,6 @@ public interface TypeEvaluator { * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ - public Object evaluate(float fraction, Object startValue, Object endValue); + public T evaluate(float fraction, T startValue, T endValue); }
\ No newline at end of file diff --git a/core/java/android/util/FloatProperty.java b/core/java/android/util/FloatProperty.java new file mode 100644 index 0000000..a67b3cb --- /dev/null +++ b/core/java/android/util/FloatProperty.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + +import android.util.Property; + +/** + * An implementation of {@link android.util.Property} to be used specifically with fields of type + * <code>float</code>. This type-specific subclass enables performance benefit by allowing + * calls to a {@link #set(Object, Float) set()} function that takes the primitive + * <code>float</code> type and avoids autoboxing and other overhead associated with the + * <code>Float</code> class. + * + * @param <T> The class on which the Property is declared. + * + * @hide + */ +public abstract class FloatProperty<T> extends Property<T, Float> { + + public FloatProperty(String name) { + super(Float.class, name); + } + + /** + * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing + * with fields of type <code>float</code>. + */ + public abstract void setValue(T object, float value); + + @Override + final public void set(T object, Float value) { + setValue(object, value); + } + +}
\ No newline at end of file diff --git a/core/java/android/util/IntProperty.java b/core/java/android/util/IntProperty.java new file mode 100644 index 0000000..459d6b2 --- /dev/null +++ b/core/java/android/util/IntProperty.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + +import android.util.Property; + +/** + * An implementation of {@link android.util.Property} to be used specifically with fields of type + * <code>int</code>. This type-specific subclass enables performance benefit by allowing + * calls to a {@link #set(Object, Integer) set()} function that takes the primitive + * <code>int</code> type and avoids autoboxing and other overhead associated with the + * <code>Integer</code> class. + * + * @param <T> The class on which the Property is declared. + * + * @hide + */ +public abstract class IntProperty<T> extends Property<T, Integer> { + + public IntProperty(String name) { + super(Integer.class, name); + } + + /** + * A type-specific override of the {@link #set(Object, Integer)} that is faster when dealing + * with fields of type <code>int</code>. + */ + public abstract void setValue(T object, int value); + + @Override + final public void set(T object, Integer value) { + set(object, value.intValue()); + } + +}
\ No newline at end of file diff --git a/core/java/android/util/NoSuchPropertyException.java b/core/java/android/util/NoSuchPropertyException.java new file mode 100644 index 0000000..b93f983 --- /dev/null +++ b/core/java/android/util/NoSuchPropertyException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + +/** + * Thrown when code requests a {@link Property} on a class that does + * not expose the appropriate method or field. + * + * @see Property#of(java.lang.Class, java.lang.Class, java.lang.String) + */ +public class NoSuchPropertyException extends RuntimeException { + + public NoSuchPropertyException(String s) { + super(s); + } + +} diff --git a/core/java/android/util/Property.java b/core/java/android/util/Property.java new file mode 100644 index 0000000..458e4c3 --- /dev/null +++ b/core/java/android/util/Property.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + + +/** + * A property is an abstraction that can be used to represent a <emb>mutable</em> value that is held + * in a <em>host</em> object. The Property's {@link #set(Object, Object)} or {@link #get(Object)} + * methods can be implemented in terms of the private fields of the host object, or via "setter" and + * "getter" methods or by some other mechanism, as appropriate. + * + * @param <T> The class on which the property is declared. + * @param <V> The type that this property represents. + */ +public abstract class Property<T, V> { + + private final String mName; + private final Class<V> mType; + + /** + * This factory method creates and returns a Property given the <code>class</code> and + * <code>name</code> parameters, where the <code>"name"</code> parameter represents either: + * <ul> + * <li>a public <code>getName()</code> method on the class which takes no arguments, plus an + * optional public <code>setName()</code> method which takes a value of the same type + * returned by <code>getName()</code> + * <li>a public <code>isName()</code> method on the class which takes no arguments, plus an + * optional public <code>setName()</code> method which takes a value of the same type + * returned by <code>isName()</code> + * <li>a public <code>name</code> field on the class + * </ul> + * + * <p>If either of the get/is method alternatives is found on the class, but an appropriate + * <code>setName()</code> method is not found, the <code>Property</code> will be + * {@link #isReadOnly() readOnly}. Calling the {@link #set(Object, Object)} method on such + * a property is allowed, but will have no effect.</p> + * + * <p>If neither the methods nor the field are found on the class a + * {@link NoSuchPropertyException} exception will be thrown.</p> + */ + public static <T, V> Property<T, V> of(Class<T> hostType, Class<V> valueType, String name) { + return new ReflectiveProperty<T, V>(hostType, valueType, name); + } + + /** + * A constructor that takes an identifying name and {@link #getType() type} for the property. + */ + public Property(Class<V> type, String name) { + mName = name; + mType = type; + } + + /** + * Returns true if the {@link #set(Object, Object)} method does not set the value on the target + * object (in which case the {@link #set(Object, Object) set()} method should throw a {@link + * NoSuchPropertyException} exception). This may happen if the Property wraps functionality that + * allows querying the underlying value but not setting it. For example, the {@link #of(Class, + * Class, String)} factory method may return a Property with name "foo" for an object that has + * only a <code>getFoo()</code> or <code>isFoo()</code> method, but no matching + * <code>setFoo()</code> method. + */ + public boolean isReadOnly() { + return false; + } + + /** + * Sets the value on <code>object</code> which this property represents. If the method is unable + * to set the value on the target object, it will throw a {@link NoSuchPropertyException} + * exception. + */ + public void set(T object, V value) { + throw new NoSuchPropertyException("Property is read-only; set() is not implemented"); + } + + /** + * Returns the current value that this property represents on the given <code>object</code>. + */ + public abstract V get(T object); + + /** + * Returns the name for this property. + */ + public String getName() { + return mName; + } + + /** + * Returns the type for this property. + */ + public Class<V> getType() { + return mType; + } +} diff --git a/core/java/android/util/ReflectiveProperty.java b/core/java/android/util/ReflectiveProperty.java new file mode 100644 index 0000000..7bd7428 --- /dev/null +++ b/core/java/android/util/ReflectiveProperty.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Internal class to automatically generate a Property for a given class/name pair, given the + * specification of {@link Property#of(java.lang.Class, java.lang.Class, java.lang.String)} + */ +class ReflectiveProperty<T, V> extends Property<T, V> { + + private static final String PREFIX_GET = "get"; + private static final String PREFIX_IS = "is"; + private static final String PREFIX_SET = "set"; + private Method mSetter; + private Method mGetter; + private Field mField; + + /** + * For given property name 'name', look for getName/isName method or 'name' field. + * Also look for setName method (optional - could be readonly). Failing method getters and + * field results in throwing NoSuchPropertyException. + * + * @param propertyHolder The class on which the methods or field are found + * @param name The name of the property, where this name is capitalized and appended to + * "get" and "is to search for the appropriate methods. If the get/is methods are not found, + * the constructor will search for a field with that exact name. + */ + public ReflectiveProperty(Class<T> propertyHolder, Class<V> valueType, String name) { + // TODO: cache reflection info for each new class/name pair + super(valueType, name); + char firstLetter = Character.toUpperCase(name.charAt(0)); + String theRest = name.substring(1); + String capitalizedName = firstLetter + theRest; + String getterName = PREFIX_GET + capitalizedName; + try { + mGetter = propertyHolder.getMethod(getterName, (Class<?>[])null); + } catch (NoSuchMethodException e) { + // getName() not available - try isName() instead + getterName = PREFIX_IS + capitalizedName; + try { + mGetter = propertyHolder.getMethod(getterName, (Class<?>[])null); + } catch (NoSuchMethodException e1) { + // Try public field instead + try { + mField = propertyHolder.getField(name); + Class fieldType = mField.getType(); + if (!typesMatch(valueType, fieldType)) { + throw new NoSuchPropertyException("Underlying type (" + fieldType + ") " + + "does not match Property type (" + valueType + ")"); + } + return; + } catch (NoSuchFieldException e2) { + // no way to access property - throw appropriate exception + throw new NoSuchPropertyException("No accessor method or field found for" + + " property with name " + name); + } + } + } + Class getterType = mGetter.getReturnType(); + // Check to make sure our getter type matches our valueType + if (!typesMatch(valueType, getterType)) { + throw new NoSuchPropertyException("Underlying type (" + getterType + ") " + + "does not match Property type (" + valueType + ")"); + } + String setterName = PREFIX_SET + capitalizedName; + try { + mSetter = propertyHolder.getMethod(setterName, getterType); + } catch (NoSuchMethodException ignored) { + // Okay to not have a setter - just a readonly property + } + } + + /** + * Utility method to check whether the type of the underlying field/method on the target + * object matches the type of the Property. The extra checks for primitive types are because + * generics will force the Property type to be a class, whereas the type of the underlying + * method/field will probably be a primitive type instead. Accept float as matching Float, + * etc. + */ + private boolean typesMatch(Class<V> valueType, Class getterType) { + if (getterType != valueType) { + if (getterType.isPrimitive()) { + return (getterType == float.class && valueType == Float.class) || + (getterType == int.class && valueType == Integer.class) || + (getterType == boolean.class && valueType == Boolean.class) || + (getterType == long.class && valueType == Long.class) || + (getterType == double.class && valueType == Double.class) || + (getterType == short.class && valueType == Short.class) || + (getterType == byte.class && valueType == Byte.class) || + (getterType == char.class && valueType == Character.class); + } + return false; + } + return true; + } + + @Override + public void set(T object, V value) { + if (mSetter != null) { + try { + mSetter.invoke(object, value); + } catch (IllegalAccessException e) { + throw new AssertionError(); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } + } else if (mField != null) { + try { + mField.set(object, value); + } catch (IllegalAccessException e) { + throw new AssertionError(); + } + } else { + throw new NoSuchPropertyException("Property is read-only; set() is not implemented"); + } + } + + @Override + public V get(T object) { + if (mGetter != null) { + try { + return (V) mGetter.invoke(object, (Object[])null); + } catch (IllegalAccessException e) { + throw new AssertionError(); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } + } else if (mField != null) { + try { + return (V) mField.get(object); + } catch (IllegalAccessException e) { + throw new AssertionError(); + } + } + // Should not get here: there should always be a non-null getter or field + throw new AssertionError(); + } + + /** + * Returns false if there is no setter or public field underlying this Property. + */ + @Override + public boolean isReadOnly() { + return (mSetter == null && mField == null); + } +} diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java index 2603281..ec94fe7 100644 --- a/core/java/android/view/GLES20RecordingCanvas.java +++ b/core/java/android/view/GLES20RecordingCanvas.java @@ -25,7 +25,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; -import java.util.HashSet; +import java.util.ArrayList; /** * An implementation of a GL canvas that records drawing operations. @@ -37,7 +37,7 @@ class GLES20RecordingCanvas extends GLES20Canvas { // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long // as the DisplayList is alive. @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"}) - private final HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>(); + private final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5); GLES20RecordingCanvas(boolean translucent) { super(true, translucent); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 70218ac..74926bb 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,6 +16,8 @@ package android.view; +import android.util.FloatProperty; +import android.util.Property; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; @@ -12436,6 +12438,169 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit return getVerticalScrollFactor(); } + // + // Properties + // + /** + * A Property wrapper around the <code>alpha</code> functionality handled by the + * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. + */ + static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { + @Override + public void setValue(View object, float value) { + object.setAlpha(value); + } + + @Override + public Float get(View object) { + return object.getAlpha(); + } + }; + + /** + * A Property wrapper around the <code>translationX</code> functionality handled by the + * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. + */ + public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { + @Override + public void setValue(View object, float value) { + object.setTranslationX(value); + } + + @Override + public Float get(View object) { + return object.getTranslationX(); + } + }; + + /** + * A Property wrapper around the <code>translationY</code> functionality handled by the + * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. + */ + public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { + @Override + public void setValue(View object, float value) { + object.setTranslationY(value); + } + + @Override + public Float get(View object) { + return object.getTranslationY(); + } + }; + + /** + * A Property wrapper around the <code>x</code> functionality handled by the + * {@link View#setX(float)} and {@link View#getX()} methods. + */ + public static Property<View, Float> X = new FloatProperty<View>("x") { + @Override + public void setValue(View object, float value) { + object.setX(value); + } + + @Override + public Float get(View object) { + return object.getX(); + } + }; + + /** + * A Property wrapper around the <code>y</code> functionality handled by the + * {@link View#setY(float)} and {@link View#getY()} methods. + */ + public static Property<View, Float> Y = new FloatProperty<View>("y") { + @Override + public void setValue(View object, float value) { + object.setY(value); + } + + @Override + public Float get(View object) { + return object.getY(); + } + }; + + /** + * A Property wrapper around the <code>rotation</code> functionality handled by the + * {@link View#setRotation(float)} and {@link View#getRotation()} methods. + */ + public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { + @Override + public void setValue(View object, float value) { + object.setRotation(value); + } + + @Override + public Float get(View object) { + return object.getRotation(); + } + }; + + /** + * A Property wrapper around the <code>rotationX</code> functionality handled by the + * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. + */ + public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { + @Override + public void setValue(View object, float value) { + object.setRotationX(value); + } + + @Override + public Float get(View object) { + return object.getRotationX(); + } + }; + + /** + * A Property wrapper around the <code>rotationY</code> functionality handled by the + * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. + */ + public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { + @Override + public void setValue(View object, float value) { + object.setRotationY(value); + } + + @Override + public Float get(View object) { + return object.getRotationY(); + } + }; + + /** + * A Property wrapper around the <code>scaleX</code> functionality handled by the + * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. + */ + public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { + @Override + public void setValue(View object, float value) { + object.setScaleX(value); + } + + @Override + public Float get(View object) { + return object.getScaleX(); + } + }; + + /** + * A Property wrapper around the <code>scaleY</code> functionality handled by the + * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. + */ + public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { + @Override + public void setValue(View object, float value) { + object.setScaleY(value); + } + + @Override + public Float get(View object) { + return object.getScaleY(); + } + }; + /** * A MeasureSpec encapsulates the layout requirements passed from parent to child. * Each MeasureSpec represents a requirement for either the width or the height. |