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