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