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