ObjectAnimator.java revision e48ef2a3efedebdcc351b60d2f3c35c987811938
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 PathKeyframes keyframes = KeyframeSet.ofPath(path); 243 PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName, 244 keyframes.createXIntKeyframes()); 245 PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName, 246 keyframes.createYIntKeyframes()); 247 return ofPropertyValuesHolder(target, x, y); 248 } 249 250 /** 251 * Constructs and returns an ObjectAnimator that animates between int values. A single 252 * value implies that that value is the one being animated to. Two values imply starting 253 * and ending values. More than two values imply a starting value, values to animate through 254 * along the way, and an ending value (these values will be distributed evenly across 255 * the duration of the animation). 256 * 257 * @param target The object whose property is to be animated. 258 * @param property The property being animated. 259 * @param values A set of values that the animation will animate between over time. 260 * @return An ObjectAnimator object that is set up to animate between the given values. 261 */ 262 public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> property, int... values) { 263 ObjectAnimator anim = new ObjectAnimator(target, property); 264 anim.setIntValues(values); 265 return anim; 266 } 267 268 /** 269 * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> 270 * using two properties. A <code>Path</code></> animation moves in two dimensions, animating 271 * coordinates <code>(x, y)</code> together to follow the line. In this variation, the 272 * coordinates are integers that are set to separate properties, <code>xProperty</code> and 273 * <code>yProperty</code>. 274 * 275 * @param target The object whose properties are to be animated. 276 * @param xProperty The property for the x coordinate being animated. 277 * @param yProperty The property for the y coordinate being animated. 278 * @param path The <code>Path</code> to animate values along. 279 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 280 */ 281 public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty, 282 Property<T, Integer> yProperty, Path path) { 283 PathKeyframes keyframes = KeyframeSet.ofPath(path); 284 PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty, 285 keyframes.createXIntKeyframes()); 286 PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty, 287 keyframes.createYIntKeyframes()); 288 return ofPropertyValuesHolder(target, x, y); 289 } 290 291 /** 292 * Constructs and returns an ObjectAnimator that animates over int values for a multiple 293 * parameters setter. Only public methods that take only int parameters are supported. 294 * Each <code>int[]</code> contains a complete set of parameters to the setter method. 295 * At least two <code>int[]</code> values must be provided, a start and end. More than two 296 * values imply a starting value, values to animate through along the way, and an ending 297 * value (these values will be distributed evenly across the duration of the animation). 298 * 299 * @param target The object whose property is to be animated. This object may 300 * have a public method on it called <code>setName()</code>, where <code>name</code> is 301 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 302 * be the case-sensitive complete name of the public setter method. 303 * @param propertyName The name of the property being animated or the name of the setter method. 304 * @param values A set of values that the animation will animate between over time. 305 * @return An ObjectAnimator object that is set up to animate between the given values. 306 */ 307 public static ObjectAnimator ofMultiInt(Object target, String propertyName, int[][] values) { 308 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, values); 309 return ofPropertyValuesHolder(target, pvh); 310 } 311 312 /** 313 * Constructs and returns an ObjectAnimator that animates the target using a multi-int setter 314 * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions, 315 * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the 316 * coordinates are integer x and y coordinates used in the first and second parameter of the 317 * setter, respectively. 318 * 319 * @param target The object whose property is to be animated. This object may 320 * have a public method on it called <code>setName()</code>, where <code>name</code> is 321 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 322 * be the case-sensitive complete name of the public setter method. 323 * @param propertyName The name of the property being animated or the name of the setter method. 324 * @param path The <code>Path</code> to animate values along. 325 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 326 */ 327 public static ObjectAnimator ofMultiInt(Object target, String propertyName, Path path) { 328 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, path); 329 return ofPropertyValuesHolder(target, pvh); 330 } 331 332 /** 333 * Constructs and returns an ObjectAnimator that animates over values for a multiple int 334 * parameters setter. Only public methods that take only int parameters are supported. 335 * <p>At least two values must be provided, a start and end. More than two 336 * values imply a starting value, values to animate through along the way, and an ending 337 * value (these values will be distributed evenly across the duration of the animation).</p> 338 * 339 * @param target The object whose property is to be animated. This object may 340 * have a public method on it called <code>setName()</code>, where <code>name</code> is 341 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 342 * be the case-sensitive complete name of the public setter method. 343 * @param propertyName The name of the property being animated or the name of the setter method. 344 * @param converter Converts T objects into int parameters for the multi-value setter. 345 * @param evaluator A TypeEvaluator that will be called on each animation frame to 346 * provide the necessary interpolation between the Object values to derive the animated 347 * value. 348 * @param values A set of values that the animation will animate between over time. 349 * @return An ObjectAnimator object that is set up to animate between the given values. 350 */ 351 public static <T> ObjectAnimator ofMultiInt(Object target, String propertyName, 352 TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values) { 353 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, converter, 354 evaluator, values); 355 return ObjectAnimator.ofPropertyValuesHolder(target, pvh); 356 } 357 358 /** 359 * Constructs and returns an ObjectAnimator that animates between color values. A single 360 * value implies that that value is the one being animated to. Two values imply starting 361 * and ending values. More than two values imply a starting value, values to animate through 362 * along the way, and an ending value (these values will be distributed evenly across 363 * the duration of the animation). 364 * 365 * @param target The object whose property is to be animated. This object should 366 * have a public method on it called <code>setName()</code>, where <code>name</code> is 367 * the value of the <code>propertyName</code> parameter. 368 * @param propertyName The name of the property being animated. 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 public static ObjectAnimator ofArgb(Object target, String propertyName, int... values) { 373 ObjectAnimator animator = ofInt(target, propertyName, values); 374 animator.setEvaluator(ArgbEvaluator.getInstance()); 375 return animator; 376 } 377 378 /** 379 * Constructs and returns an ObjectAnimator that animates between color values. A single 380 * value implies that that value is the one being animated to. Two values imply starting 381 * and ending values. More than two values imply a starting value, values to animate through 382 * along the way, and an ending value (these values will be distributed evenly across 383 * the duration of the animation). 384 * 385 * @param target The object whose property is to be animated. 386 * @param property The property being animated. 387 * @param values A set of values that the animation will animate between over time. 388 * @return An ObjectAnimator object that is set up to animate between the given values. 389 */ 390 public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property, 391 int... values) { 392 ObjectAnimator animator = ofInt(target, property, values); 393 animator.setEvaluator(ArgbEvaluator.getInstance()); 394 return animator; 395 } 396 397 /** 398 * Constructs and returns an ObjectAnimator that animates between float values. A single 399 * value implies that that value is the one being animated to. Two values imply starting 400 * and ending values. More than two values imply a starting value, values to animate through 401 * along the way, and an ending value (these values will be distributed evenly across 402 * the duration of the animation). 403 * 404 * @param target The object whose property is to be animated. This object should 405 * have a public method on it called <code>setName()</code>, where <code>name</code> is 406 * the value of the <code>propertyName</code> parameter. 407 * @param propertyName The name of the property being animated. 408 * @param values A set of values that the animation will animate between over time. 409 * @return An ObjectAnimator object that is set up to animate between the given values. 410 */ 411 public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { 412 ObjectAnimator anim = new ObjectAnimator(target, propertyName); 413 anim.setFloatValues(values); 414 return anim; 415 } 416 417 /** 418 * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> 419 * using two properties. A <code>Path</code></> animation moves in two dimensions, animating 420 * coordinates <code>(x, y)</code> together to follow the line. In this variation, the 421 * coordinates are floats that are set to separate properties designated by 422 * <code>xPropertyName</code> and <code>yPropertyName</code>. 423 * 424 * @param target The object whose properties are to be animated. This object should 425 * have public methods on it called <code>setNameX()</code> and 426 * <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code> 427 * are the value of the <code>xPropertyName</code> and <code>yPropertyName</code> 428 * parameters, respectively. 429 * @param xPropertyName The name of the property for the x coordinate being animated. 430 * @param yPropertyName The name of the property for the y coordinate being animated. 431 * @param path The <code>Path</code> to animate values along. 432 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 433 */ 434 public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName, 435 Path path) { 436 PathKeyframes keyframes = KeyframeSet.ofPath(path); 437 PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName, 438 keyframes.createXFloatKeyframes()); 439 PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName, 440 keyframes.createYFloatKeyframes()); 441 return ofPropertyValuesHolder(target, x, y); 442 } 443 444 /** 445 * Constructs and returns an ObjectAnimator that animates between float values. A single 446 * value implies that that value is the one being animated to. Two values imply starting 447 * and ending values. More than two values imply a starting value, values to animate through 448 * along the way, and an ending value (these values will be distributed evenly across 449 * the duration of the animation). 450 * 451 * @param target The object whose property is to be animated. 452 * @param property The property being animated. 453 * @param values A set of values that the animation will animate between over time. 454 * @return An ObjectAnimator object that is set up to animate between the given values. 455 */ 456 public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property, 457 float... values) { 458 ObjectAnimator anim = new ObjectAnimator(target, property); 459 anim.setFloatValues(values); 460 return anim; 461 } 462 463 /** 464 * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> 465 * using two properties. A <code>Path</code></> animation moves in two dimensions, animating 466 * coordinates <code>(x, y)</code> together to follow the line. In this variation, the 467 * coordinates are floats that are set to separate properties, <code>xProperty</code> and 468 * <code>yProperty</code>. 469 * 470 * @param target The object whose properties are to be animated. 471 * @param xProperty The property for the x coordinate being animated. 472 * @param yProperty The property for the y coordinate being animated. 473 * @param path The <code>Path</code> to animate values along. 474 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 475 */ 476 public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty, 477 Property<T, Float> yProperty, Path path) { 478 PathKeyframes keyframes = KeyframeSet.ofPath(path); 479 PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty, 480 keyframes.createXFloatKeyframes()); 481 PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty, 482 keyframes.createYFloatKeyframes()); 483 return ofPropertyValuesHolder(target, x, y); 484 } 485 486 /** 487 * Constructs and returns an ObjectAnimator that animates over float values for a multiple 488 * parameters setter. Only public methods that take only float parameters are supported. 489 * Each <code>float[]</code> contains a complete set of parameters to the setter method. 490 * At least two <code>float[]</code> values must be provided, a start and end. More than two 491 * values imply a starting value, values to animate through along the way, and an ending 492 * value (these values will be distributed evenly across the duration of the animation). 493 * 494 * @param target The object whose property is to be animated. This object may 495 * have a public method on it called <code>setName()</code>, where <code>name</code> is 496 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 497 * be the case-sensitive complete name of the public setter method. 498 * @param propertyName The name of the property being animated or the name of the setter method. 499 * @param values A set of values that the animation will animate between over time. 500 * @return An ObjectAnimator object that is set up to animate between the given values. 501 */ 502 public static ObjectAnimator ofMultiFloat(Object target, String propertyName, 503 float[][] values) { 504 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, values); 505 return ofPropertyValuesHolder(target, pvh); 506 } 507 508 /** 509 * Constructs and returns an ObjectAnimator that animates the target using a multi-float setter 510 * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions, 511 * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the 512 * coordinates are float x and y coordinates used in the first and second parameter of the 513 * setter, respectively. 514 * 515 * @param target The object whose property is to be animated. This object may 516 * have a public method on it called <code>setName()</code>, where <code>name</code> is 517 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 518 * be the case-sensitive complete name of the public setter method. 519 * @param propertyName The name of the property being animated or the name of the setter method. 520 * @param path The <code>Path</code> to animate values along. 521 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 522 */ 523 public static ObjectAnimator ofMultiFloat(Object target, String propertyName, Path path) { 524 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, path); 525 return ofPropertyValuesHolder(target, pvh); 526 } 527 528 /** 529 * Constructs and returns an ObjectAnimator that animates over values for a multiple float 530 * parameters setter. Only public methods that take only float parameters are supported. 531 * <p>At least two values must be provided, a start and end. More than two 532 * values imply a starting value, values to animate through along the way, and an ending 533 * value (these values will be distributed evenly across the duration of the animation).</p> 534 * 535 * @param target The object whose property is to be animated. This object may 536 * have a public method on it called <code>setName()</code>, where <code>name</code> is 537 * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also 538 * be the case-sensitive complete name of the public setter method. 539 * @param propertyName The name of the property being animated or the name of the setter method. 540 * @param converter Converts T objects into float parameters for the multi-value setter. 541 * @param evaluator A TypeEvaluator that will be called on each animation frame to 542 * provide the necessary interpolation between the Object values to derive the animated 543 * value. 544 * @param values A set of values that the animation will animate between over time. 545 * @return An ObjectAnimator object that is set up to animate between the given values. 546 */ 547 public static <T> ObjectAnimator ofMultiFloat(Object target, String propertyName, 548 TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values) { 549 PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, converter, 550 evaluator, values); 551 return ObjectAnimator.ofPropertyValuesHolder(target, pvh); 552 } 553 554 /** 555 * Constructs and returns an ObjectAnimator that animates between Object values. A single 556 * value implies that that value is the one being animated to. Two values imply starting 557 * and ending values. More than two values imply a starting value, values to animate through 558 * along the way, and an ending value (these values will be distributed evenly across 559 * the duration of the animation). 560 * 561 * @param target The object whose property is to be animated. This object should 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. 564 * @param propertyName The name of the property being animated. 565 * @param evaluator A TypeEvaluator that will be called on each animation frame to 566 * provide the necessary interpolation between the Object values to derive the animated 567 * value. 568 * @param values A set of values that the animation will animate between over time. 569 * @return An ObjectAnimator object that is set up to animate between the given values. 570 */ 571 public static ObjectAnimator ofObject(Object target, String propertyName, 572 TypeEvaluator evaluator, Object... values) { 573 ObjectAnimator anim = new ObjectAnimator(target, propertyName); 574 anim.setObjectValues(values); 575 anim.setEvaluator(evaluator); 576 return anim; 577 } 578 579 /** 580 * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>. 581 * A <code>Path</code></> animation moves in two dimensions, animating coordinates 582 * <code>(x, y)</code> together to follow the line. This variant animates the coordinates 583 * in a <code>PointF</code> to follow the <code>Path</code>. If the <code>Property</code> 584 * associated with <code>propertyName</code> uses a type other than <code>PointF</code>, 585 * <code>converter</code> can be used to change from <code>PointF</code> to the type 586 * associated with the <code>Property</code>. 587 * 588 * @param target The object whose property is to be animated. This object should 589 * have a public method on it called <code>setName()</code>, where <code>name</code> is 590 * the value of the <code>propertyName</code> parameter. 591 * @param propertyName The name of the property being animated. 592 * @param converter Converts a PointF to the type associated with the setter. May be 593 * null if conversion is unnecessary. 594 * @param path The <code>Path</code> to animate values along. 595 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 596 */ 597 @NonNull 598 public static ObjectAnimator ofObject(Object target, String propertyName, 599 @Nullable TypeConverter<PointF, ?> converter, Path path) { 600 PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(propertyName, converter, path); 601 return ofPropertyValuesHolder(target, pvh); 602 } 603 604 /** 605 * Constructs and returns an ObjectAnimator that animates between Object values. A single 606 * value implies that that value is the one being animated to. Two values imply starting 607 * and ending values. More than two values imply a starting value, values to animate through 608 * along the way, and an ending value (these values will be distributed evenly across 609 * the duration of the animation). 610 * 611 * @param target The object whose property is to be animated. 612 * @param property The property being animated. 613 * @param evaluator A TypeEvaluator that will be called on each animation frame to 614 * provide the necessary interpolation between the Object values to derive the animated 615 * value. 616 * @param values A set of values that the animation will animate between over time. 617 * @return An ObjectAnimator object that is set up to animate between the given values. 618 */ 619 @NonNull 620 public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property, 621 TypeEvaluator<V> evaluator, V... values) { 622 ObjectAnimator anim = new ObjectAnimator(target, property); 623 anim.setObjectValues(values); 624 anim.setEvaluator(evaluator); 625 return anim; 626 } 627 628 /** 629 * Constructs and returns an ObjectAnimator that animates between Object values. A single 630 * value implies that that value is the one being animated to. Two values imply starting 631 * and ending values. More than two values imply a starting value, values to animate through 632 * along the way, and an ending value (these values will be distributed evenly across 633 * the duration of the animation). This variant supplies a <code>TypeConverter</code> to 634 * convert from the animated values to the type of the property. If only one value is 635 * supplied, the <code>TypeConverter</code> must be a 636 * {@link android.animation.BidirectionalTypeConverter} to retrieve the current value. 637 * 638 * @param target The object whose property is to be animated. 639 * @param property The property being animated. 640 * @param converter Converts the animated object to the Property type. 641 * @param evaluator A TypeEvaluator that will be called on each animation frame to 642 * provide the necessary interpolation between the Object values to derive the animated 643 * value. 644 * @param values A set of values that the animation will animate between over time. 645 * @return An ObjectAnimator object that is set up to animate between the given values. 646 */ 647 @NonNull 648 public static <T, V, P> ObjectAnimator ofObject(T target, Property<T, P> property, 649 TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values) { 650 PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, evaluator, 651 values); 652 return ofPropertyValuesHolder(target, pvh); 653 } 654 655 /** 656 * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>. 657 * A <code>Path</code></> animation moves in two dimensions, animating coordinates 658 * <code>(x, y)</code> together to follow the line. This variant animates the coordinates 659 * in a <code>PointF</code> to follow the <code>Path</code>. If <code>property</code> 660 * uses a type other than <code>PointF</code>, <code>converter</code> can be used to change 661 * from <code>PointF</code> to the type associated with the <code>Property</code>. 662 * 663 * <p>The PointF passed to <code>converter</code> or <code>property</code>, if 664 * <code>converter</code> is <code>null</code>, is reused on each animation frame and should 665 * not be stored by the setter or TypeConverter.</p> 666 * 667 * @param target The object whose property is to be animated. 668 * @param property The property being animated. Should not be null. 669 * @param converter Converts a PointF to the type associated with the setter. May be 670 * null if conversion is unnecessary. 671 * @param path The <code>Path</code> to animate values along. 672 * @return An ObjectAnimator object that is set up to animate along <code>path</code>. 673 */ 674 @NonNull 675 public static <T, V> ObjectAnimator ofObject(T target, @NonNull Property<T, V> property, 676 @Nullable TypeConverter<PointF, V> converter, Path path) { 677 PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, path); 678 return ofPropertyValuesHolder(target, pvh); 679 } 680 681 /** 682 * Constructs and returns an ObjectAnimator that animates between the sets of values specified 683 * in <code>PropertyValueHolder</code> objects. This variant should be used when animating 684 * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows 685 * you to associate a set of animation values with a property name. 686 * 687 * @param target The object whose property is to be animated. Depending on how the 688 * PropertyValuesObjects were constructed, the target object should either have the {@link 689 * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the 690 * PropertyValuesHOlder objects were created with property names) the target object should have 691 * public methods on it called <code>setName()</code>, where <code>name</code> is the name of 692 * the property passed in as the <code>propertyName</code> parameter for each of the 693 * PropertyValuesHolder objects. 694 * @param values A set of PropertyValuesHolder objects whose values will be animated between 695 * over time. 696 * @return An ObjectAnimator object that is set up to animate between the given values. 697 */ 698 @NonNull 699 public static ObjectAnimator ofPropertyValuesHolder(Object target, 700 PropertyValuesHolder... values) { 701 ObjectAnimator anim = new ObjectAnimator(); 702 anim.setTarget(target); 703 anim.setValues(values); 704 return anim; 705 } 706 707 @Override 708 public void setIntValues(int... values) { 709 if (mValues == null || mValues.length == 0) { 710 // No values yet - this animator is being constructed piecemeal. Init the values with 711 // whatever the current propertyName is 712 if (mProperty != null) { 713 setValues(PropertyValuesHolder.ofInt(mProperty, values)); 714 } else { 715 setValues(PropertyValuesHolder.ofInt(mPropertyName, values)); 716 } 717 } else { 718 super.setIntValues(values); 719 } 720 } 721 722 @Override 723 public void setFloatValues(float... values) { 724 if (mValues == null || mValues.length == 0) { 725 // No values yet - this animator is being constructed piecemeal. Init the values with 726 // whatever the current propertyName is 727 if (mProperty != null) { 728 setValues(PropertyValuesHolder.ofFloat(mProperty, values)); 729 } else { 730 setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); 731 } 732 } else { 733 super.setFloatValues(values); 734 } 735 } 736 737 @Override 738 public void setObjectValues(Object... values) { 739 if (mValues == null || mValues.length == 0) { 740 // No values yet - this animator is being constructed piecemeal. Init the values with 741 // whatever the current propertyName is 742 if (mProperty != null) { 743 setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator) null, values)); 744 } else { 745 setValues(PropertyValuesHolder.ofObject(mPropertyName, 746 (TypeEvaluator) null, values)); 747 } 748 } else { 749 super.setObjectValues(values); 750 } 751 } 752 753 /** 754 * autoCancel controls whether an ObjectAnimator will be canceled automatically 755 * when any other ObjectAnimator with the same target and properties is started. 756 * Setting this flag may make it easier to run different animators on the same target 757 * object without having to keep track of whether there are conflicting animators that 758 * need to be manually canceled. Canceling animators must have the same exact set of 759 * target properties, in the same order. 760 * 761 * @param cancel Whether future ObjectAnimators with the same target and properties 762 * as this ObjectAnimator will cause this ObjectAnimator to be canceled. 763 */ 764 public void setAutoCancel(boolean cancel) { 765 mAutoCancel = cancel; 766 } 767 768 private boolean hasSameTargetAndProperties(@Nullable Animator anim) { 769 if (anim instanceof ObjectAnimator) { 770 PropertyValuesHolder[] theirValues = ((ObjectAnimator) anim).getValues(); 771 if (((ObjectAnimator) anim).getTarget() == getTarget() && 772 mValues.length == theirValues.length) { 773 for (int i = 0; i < mValues.length; ++i) { 774 PropertyValuesHolder pvhMine = mValues[i]; 775 PropertyValuesHolder pvhTheirs = theirValues[i]; 776 if (pvhMine.getPropertyName() == null || 777 !pvhMine.getPropertyName().equals(pvhTheirs.getPropertyName())) { 778 return false; 779 } 780 } 781 return true; 782 } 783 } 784 return false; 785 } 786 787 @Override 788 public void start() { 789 // See if any of the current active/pending animators need to be canceled 790 AnimationHandler handler = sAnimationHandler.get(); 791 if (handler != null) { 792 int numAnims = handler.mAnimations.size(); 793 for (int i = numAnims - 1; i >= 0; i--) { 794 if (handler.mAnimations.get(i) instanceof ObjectAnimator) { 795 ObjectAnimator anim = (ObjectAnimator) handler.mAnimations.get(i); 796 if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) { 797 anim.cancel(); 798 } 799 } 800 } 801 numAnims = handler.mPendingAnimations.size(); 802 for (int i = numAnims - 1; i >= 0; i--) { 803 if (handler.mPendingAnimations.get(i) instanceof ObjectAnimator) { 804 ObjectAnimator anim = (ObjectAnimator) handler.mPendingAnimations.get(i); 805 if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) { 806 anim.cancel(); 807 } 808 } 809 } 810 numAnims = handler.mDelayedAnims.size(); 811 for (int i = numAnims - 1; i >= 0; i--) { 812 if (handler.mDelayedAnims.get(i) instanceof ObjectAnimator) { 813 ObjectAnimator anim = (ObjectAnimator) handler.mDelayedAnims.get(i); 814 if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) { 815 anim.cancel(); 816 } 817 } 818 } 819 } 820 if (DBG) { 821 Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration()); 822 for (int i = 0; i < mValues.length; ++i) { 823 PropertyValuesHolder pvh = mValues[i]; 824 Log.d(LOG_TAG, " Values[" + i + "]: " + 825 pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " + 826 pvh.mKeyframes.getValue(1)); 827 } 828 } 829 super.start(); 830 } 831 832 /** 833 * This function is called immediately before processing the first animation 834 * frame of an animation. If there is a nonzero <code>startDelay</code>, the 835 * function is called after that delay ends. 836 * It takes care of the final initialization steps for the 837 * animation. This includes setting mEvaluator, if the user has not yet 838 * set it up, and the setter/getter methods, if the user did not supply 839 * them. 840 * 841 * <p>Overriders of this method should call the superclass method to cause 842 * internal mechanisms to be set up correctly.</p> 843 */ 844 @Override 845 void initAnimation() { 846 if (!mInitialized) { 847 // mValueType may change due to setter/getter setup; do this before calling super.init(), 848 // which uses mValueType to set up the default type evaluator. 849 final Object target = getTarget(); 850 if (target != null) { 851 final int numValues = mValues.length; 852 for (int i = 0; i < numValues; ++i) { 853 mValues[i].setupSetterAndGetter(target); 854 } 855 } 856 super.initAnimation(); 857 } 858 } 859 860 /** 861 * Sets the length of the animation. The default duration is 300 milliseconds. 862 * 863 * @param duration The length of the animation, in milliseconds. 864 * @return ObjectAnimator The object called with setDuration(). This return 865 * value makes it easier to compose statements together that construct and then set the 866 * duration, as in 867 * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>. 868 */ 869 @Override 870 @NonNull 871 public ObjectAnimator setDuration(long duration) { 872 super.setDuration(duration); 873 return this; 874 } 875 876 877 /** 878 * The target object whose property will be animated by this animation 879 * 880 * @return The object being animated 881 */ 882 @Nullable 883 public Object getTarget() { 884 return mTarget == null ? null : mTarget.get(); 885 } 886 887 /** 888 * Sets the target object whose property will be animated by this animation. If the 889 * animator has been started, it will be canceled. 890 * 891 * @param target The object being animated 892 */ 893 @Override 894 public void setTarget(@Nullable Object target) { 895 final Object oldTarget = getTarget(); 896 if (oldTarget != target) { 897 if (isStarted()) { 898 cancel(); 899 } 900 mTarget = target == null ? null : new WeakReference<Object>(target); 901 // New target should cause re-initialization prior to starting 902 mInitialized = false; 903 } 904 } 905 906 @Override 907 public void setupStartValues() { 908 initAnimation(); 909 910 final Object target = getTarget(); 911 if (target != null) { 912 final int numValues = mValues.length; 913 for (int i = 0; i < numValues; ++i) { 914 mValues[i].setupStartValue(target); 915 } 916 } 917 } 918 919 @Override 920 public void setupEndValues() { 921 initAnimation(); 922 923 final Object target = getTarget(); 924 if (target != null) { 925 final int numValues = mValues.length; 926 for (int i = 0; i < numValues; ++i) { 927 mValues[i].setupEndValue(target); 928 } 929 } 930 } 931 932 /** 933 * This method is called with the elapsed fraction of the animation during every 934 * animation frame. This function turns the elapsed fraction into an interpolated fraction 935 * and then into an animated value (from the evaluator. The function is called mostly during 936 * animation updates, but it is also called when the <code>end()</code> 937 * function is called, to set the final value on the property. 938 * 939 * <p>Overrides of this method must call the superclass to perform the calculation 940 * of the animated value.</p> 941 * 942 * @param fraction The elapsed fraction of the animation. 943 */ 944 @Override 945 void animateValue(float fraction) { 946 final Object target = getTarget(); 947 if (mTarget != null && target == null) { 948 // We lost the target reference, cancel and clean up. 949 cancel(); 950 return; 951 } 952 953 super.animateValue(fraction); 954 int numValues = mValues.length; 955 for (int i = 0; i < numValues; ++i) { 956 mValues[i].setAnimatedValue(target); 957 } 958 } 959 960 @Override 961 public ObjectAnimator clone() { 962 final ObjectAnimator anim = (ObjectAnimator) super.clone(); 963 return anim; 964 } 965 966 @Override 967 @NonNull 968 public String toString() { 969 String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + 970 getTarget(); 971 if (mValues != null) { 972 for (int i = 0; i < mValues.length; ++i) { 973 returnVal += "\n " + mValues[i].toString(); 974 } 975 } 976 return returnVal; 977 } 978} 979