1/* 2 * Copyright (C) 2014 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 */ 16package android.support.v4.view; 17 18import android.view.View; 19import android.view.animation.Interpolator; 20 21import java.lang.ref.WeakReference; 22import java.util.WeakHashMap; 23 24public class ViewPropertyAnimatorCompat { 25 private static final String TAG = "ViewAnimatorCompat"; 26 private WeakReference<View> mView; 27 private Runnable mStartAction = null; 28 private Runnable mEndAction = null; 29 private int mOldLayerType = -1; 30 // HACK ALERT! Choosing this id knowing that the framework does not use it anywhere 31 // internally and apps should use ids higher than it 32 static final int LISTENER_TAG_ID = 0x7e000000; 33 34 35 ViewPropertyAnimatorCompat(View view) { 36 mView = new WeakReference<View>(view); 37 } 38 39 interface ViewPropertyAnimatorCompatImpl { 40 public void setDuration(ViewPropertyAnimatorCompat vpa, View view, long value); 41 public long getDuration(ViewPropertyAnimatorCompat vpa, View view); 42 public void setInterpolator(ViewPropertyAnimatorCompat vpa, View view, Interpolator value); 43 public Interpolator getInterpolator(ViewPropertyAnimatorCompat vpa, View view); 44 public void setStartDelay(ViewPropertyAnimatorCompat vpa, View view, long value); 45 public long getStartDelay(ViewPropertyAnimatorCompat vpa, View view); 46 public void alpha(ViewPropertyAnimatorCompat vpa, View view, float value); 47 public void alphaBy(ViewPropertyAnimatorCompat vpa, View view, float value); 48 public void rotation(ViewPropertyAnimatorCompat vpa, View view, float value); 49 public void rotationBy(ViewPropertyAnimatorCompat vpa, View view, float value); 50 public void rotationX(ViewPropertyAnimatorCompat vpa, View view, float value); 51 public void rotationXBy(ViewPropertyAnimatorCompat vpa, View view, float value); 52 public void rotationY(ViewPropertyAnimatorCompat vpa, View view, float value); 53 public void rotationYBy(ViewPropertyAnimatorCompat vpa, View view, float value); 54 public void scaleX(ViewPropertyAnimatorCompat vpa, View view, float value); 55 public void scaleXBy(ViewPropertyAnimatorCompat vpa, View view, float value); 56 public void scaleY(ViewPropertyAnimatorCompat vpa, View view, float value); 57 public void scaleYBy(ViewPropertyAnimatorCompat vpa, View view, float value); 58 public void cancel(ViewPropertyAnimatorCompat vpa, View view); 59 public void x(ViewPropertyAnimatorCompat vpa, View view, float value); 60 public void xBy(ViewPropertyAnimatorCompat vpa, View view, float value); 61 public void y(ViewPropertyAnimatorCompat vpa, View view, float value); 62 public void yBy(ViewPropertyAnimatorCompat vpa, View view, float value); 63 public void translationX(ViewPropertyAnimatorCompat vpa, View view, float value); 64 public void translationXBy(ViewPropertyAnimatorCompat vpa, View view, float value); 65 public void translationY(ViewPropertyAnimatorCompat vpa, View view, float value); 66 public void translationYBy(ViewPropertyAnimatorCompat vpa, View view, float value); 67 public void start(ViewPropertyAnimatorCompat vpa, View view); 68 public void withLayer(ViewPropertyAnimatorCompat vpa, View view); 69 public void withStartAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable); 70 public void withEndAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable); 71 public void setListener(ViewPropertyAnimatorCompat vpa, View view, 72 ViewPropertyAnimatorListener listener); 73 public void setUpdateListener(ViewPropertyAnimatorCompat vpa, View view, 74 ViewPropertyAnimatorUpdateListener listener); 75 }; 76 77 static class BaseViewPropertyAnimatorCompatImpl implements ViewPropertyAnimatorCompatImpl { 78 WeakHashMap<View, Runnable> mStarterMap = null; 79 80 @Override 81 public void setDuration(ViewPropertyAnimatorCompat vpa, View view, long value) { 82 // noop on versions prior to ICS 83 } 84 85 @Override 86 public void alpha(ViewPropertyAnimatorCompat vpa, View view, float value) { 87 // noop on versions prior to ICS 88 postStartMessage(vpa, view); 89 } 90 91 @Override 92 public void translationX(ViewPropertyAnimatorCompat vpa, View view, float value) { 93 // noop on versions prior to ICS 94 postStartMessage(vpa, view); 95 } 96 97 @Override 98 public void translationY(ViewPropertyAnimatorCompat vpa, View view, float value) { 99 // noop on versions prior to ICS 100 postStartMessage(vpa, view); 101 } 102 103 @Override 104 public void withEndAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable) { 105 vpa.mEndAction = runnable; 106 postStartMessage(vpa, view); 107 } 108 109 @Override 110 public long getDuration(ViewPropertyAnimatorCompat vpa, View view) { 111 return 0; 112 } 113 114 @Override 115 public void setInterpolator(ViewPropertyAnimatorCompat vpa, View view, Interpolator value) { 116 // noop on versions prior to ICS 117 } 118 119 @Override 120 public Interpolator getInterpolator(ViewPropertyAnimatorCompat vpa, View view) { 121 return null; 122 } 123 124 @Override 125 public void setStartDelay(ViewPropertyAnimatorCompat vpa, View view, long value) { 126 // noop on versions prior to ICS 127 } 128 129 @Override 130 public long getStartDelay(ViewPropertyAnimatorCompat vpa, View view) { 131 return 0; 132 } 133 134 @Override 135 public void alphaBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 136 // noop on versions prior to ICS 137 postStartMessage(vpa, view); 138 } 139 140 @Override 141 public void rotation(ViewPropertyAnimatorCompat vpa, View view, float value) { 142 // noop on versions prior to ICS 143 postStartMessage(vpa, view); 144 } 145 146 @Override 147 public void rotationBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 148 // noop on versions prior to ICS 149 postStartMessage(vpa, view); 150 } 151 152 @Override 153 public void rotationX(ViewPropertyAnimatorCompat vpa, View view, float value) { 154 // noop on versions prior to ICS 155 postStartMessage(vpa, view); 156 } 157 158 @Override 159 public void rotationXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 160 // noop on versions prior to ICS 161 postStartMessage(vpa, view); 162 } 163 164 @Override 165 public void rotationY(ViewPropertyAnimatorCompat vpa, View view, float value) { 166 // noop on versions prior to ICS 167 postStartMessage(vpa, view); 168 } 169 170 @Override 171 public void rotationYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 172 // noop on versions prior to ICS 173 postStartMessage(vpa, view); 174 } 175 176 @Override 177 public void scaleX(ViewPropertyAnimatorCompat vpa, View view, float value) { 178 // noop on versions prior to ICS 179 postStartMessage(vpa, view); 180 } 181 182 @Override 183 public void scaleXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 184 // noop on versions prior to ICS 185 postStartMessage(vpa, view); 186 } 187 188 @Override 189 public void scaleY(ViewPropertyAnimatorCompat vpa, View view, float value) { 190 // noop on versions prior to ICS 191 postStartMessage(vpa, view); 192 } 193 194 @Override 195 public void scaleYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 196 // noop on versions prior to ICS 197 postStartMessage(vpa, view); 198 } 199 200 @Override 201 public void cancel(ViewPropertyAnimatorCompat vpa, View view) { 202 // noop on versions prior to ICS 203 postStartMessage(vpa, view); 204 } 205 206 @Override 207 public void x(ViewPropertyAnimatorCompat vpa, View view, float value) { 208 // noop on versions prior to ICS 209 postStartMessage(vpa, view); 210 } 211 212 @Override 213 public void xBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 214 // noop on versions prior to ICS 215 postStartMessage(vpa, view); 216 } 217 218 @Override 219 public void y(ViewPropertyAnimatorCompat vpa, View view, float value) { 220 // noop on versions prior to ICS 221 postStartMessage(vpa, view); 222 } 223 224 @Override 225 public void yBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 226 // noop on versions prior to ICS 227 postStartMessage(vpa, view); 228 } 229 230 @Override 231 public void translationXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 232 // noop on versions prior to ICS 233 postStartMessage(vpa, view); 234 } 235 236 @Override 237 public void translationYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 238 // noop on versions prior to ICS 239 postStartMessage(vpa, view); 240 } 241 242 @Override 243 public void start(ViewPropertyAnimatorCompat vpa, View view) { 244 removeStartMessage(view); 245 startAnimation(vpa, view); 246 } 247 248 @Override 249 public void withLayer(ViewPropertyAnimatorCompat vpa, View view) { 250 // noop on versions prior to ICS 251 } 252 253 @Override 254 public void withStartAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable) { 255 vpa.mStartAction = runnable; 256 postStartMessage(vpa, view); 257 } 258 259 @Override 260 public void setListener(ViewPropertyAnimatorCompat vpa, View view, ViewPropertyAnimatorListener listener) { 261 view.setTag(LISTENER_TAG_ID, listener); 262 } 263 264 @Override 265 public void setUpdateListener(ViewPropertyAnimatorCompat vpa, View view, ViewPropertyAnimatorUpdateListener listener) { 266 // noop 267 } 268 269 private void startAnimation(ViewPropertyAnimatorCompat vpa, View view) { 270 Object listenerTag = view.getTag(LISTENER_TAG_ID); 271 ViewPropertyAnimatorListener listener = null; 272 if (listenerTag instanceof ViewPropertyAnimatorListener) { 273 listener = (ViewPropertyAnimatorListener) listenerTag; 274 } 275 Runnable startAction = vpa.mStartAction; 276 Runnable endAction = vpa.mEndAction; 277 if (startAction != null) { 278 startAction.run(); 279 } 280 if (listener != null) { 281 listener.onAnimationStart(view); 282 listener.onAnimationEnd(view); 283 } 284 if (endAction != null) { 285 endAction.run(); 286 } 287 if (mStarterMap != null) { 288 mStarterMap.remove(view); 289 } 290 } 291 292 class Starter implements Runnable { 293 WeakReference<View> mViewRef; 294 ViewPropertyAnimatorCompat mVpa; 295 296 private Starter(ViewPropertyAnimatorCompat vpa, View view) { 297 mViewRef = new WeakReference<View>(view); 298 mVpa = vpa; 299 } 300 301 @Override 302 public void run() { 303 startAnimation(mVpa, mViewRef.get()); 304 } 305 }; 306 307 private void removeStartMessage(View view) { 308 Runnable starter = null; 309 if (mStarterMap != null) { 310 starter = mStarterMap.get(view); 311 if (starter != null) { 312 view.removeCallbacks(starter); 313 } 314 } 315 } 316 317 private void postStartMessage(ViewPropertyAnimatorCompat vpa, View view) { 318 Runnable starter = null; 319 if (mStarterMap != null) { 320 starter = mStarterMap.get(view); 321 } 322 if (starter == null) { 323 starter = new Starter(vpa, view); 324 if (mStarterMap == null) { 325 mStarterMap = new WeakHashMap<View, Runnable>(); 326 } 327 mStarterMap.put(view, starter); 328 } 329 view.removeCallbacks(starter); 330 view.post(starter); 331 } 332 333 } 334 335 static class ICSViewPropertyAnimatorCompatImpl extends BaseViewPropertyAnimatorCompatImpl { 336 WeakHashMap<View, Integer> mLayerMap = null; 337 338 @Override 339 public void setDuration(ViewPropertyAnimatorCompat vpa, View view, long value) { 340 ViewPropertyAnimatorCompatICS.setDuration(view, value); 341 } 342 343 @Override 344 public void alpha(ViewPropertyAnimatorCompat vpa, View view, float value) { 345 ViewPropertyAnimatorCompatICS.alpha(view, value); 346 } 347 348 @Override 349 public void translationX(ViewPropertyAnimatorCompat vpa, View view, float value) { 350 ViewPropertyAnimatorCompatICS.translationX(view, value); 351 } 352 353 @Override 354 public void translationY(ViewPropertyAnimatorCompat vpa, View view, float value) { 355 ViewPropertyAnimatorCompatICS.translationY(view, value); 356 } 357 358 @Override 359 public long getDuration(ViewPropertyAnimatorCompat vpa, View view) { 360 return ViewPropertyAnimatorCompatICS.getDuration(view); 361 } 362 363 @Override 364 public void setInterpolator(ViewPropertyAnimatorCompat vpa, View view, Interpolator value) { 365 ViewPropertyAnimatorCompatICS.setInterpolator(view, value); 366 } 367 368 @Override 369 public void setStartDelay(ViewPropertyAnimatorCompat vpa, View view, long value) { 370 ViewPropertyAnimatorCompatICS.setStartDelay(view, value); 371 } 372 373 @Override 374 public long getStartDelay(ViewPropertyAnimatorCompat vpa, View view) { 375 return ViewPropertyAnimatorCompatICS.getStartDelay(view); 376 } 377 378 @Override 379 public void alphaBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 380 ViewPropertyAnimatorCompatICS.alphaBy(view, value); 381 } 382 383 @Override 384 public void rotation(ViewPropertyAnimatorCompat vpa, View view, float value) { 385 ViewPropertyAnimatorCompatICS.rotation(view, value); 386 } 387 388 @Override 389 public void rotationBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 390 ViewPropertyAnimatorCompatICS.rotationBy(view, value); 391 } 392 393 @Override 394 public void rotationX(ViewPropertyAnimatorCompat vpa, View view, float value) { 395 ViewPropertyAnimatorCompatICS.rotationX(view, value); 396 } 397 398 @Override 399 public void rotationXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 400 ViewPropertyAnimatorCompatICS.rotationXBy(view, value); 401 } 402 403 @Override 404 public void rotationY(ViewPropertyAnimatorCompat vpa, View view, float value) { 405 ViewPropertyAnimatorCompatICS.rotationY(view, value); 406 } 407 408 @Override 409 public void rotationYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 410 ViewPropertyAnimatorCompatICS.rotationYBy(view, value); 411 } 412 413 @Override 414 public void scaleX(ViewPropertyAnimatorCompat vpa, View view, float value) { 415 ViewPropertyAnimatorCompatICS.scaleX(view, value); 416 } 417 418 @Override 419 public void scaleXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 420 ViewPropertyAnimatorCompatICS.scaleXBy(view, value); 421 } 422 423 @Override 424 public void scaleY(ViewPropertyAnimatorCompat vpa, View view, float value) { 425 ViewPropertyAnimatorCompatICS.scaleY(view, value); 426 } 427 428 @Override 429 public void scaleYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 430 ViewPropertyAnimatorCompatICS.scaleYBy(view, value); 431 } 432 433 @Override 434 public void cancel(ViewPropertyAnimatorCompat vpa, View view) { 435 ViewPropertyAnimatorCompatICS.cancel(view); 436 } 437 438 @Override 439 public void x(ViewPropertyAnimatorCompat vpa, View view, float value) { 440 ViewPropertyAnimatorCompatICS.x(view, value); 441 } 442 443 @Override 444 public void xBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 445 ViewPropertyAnimatorCompatICS.xBy(view, value); 446 } 447 448 @Override 449 public void y(ViewPropertyAnimatorCompat vpa, View view, float value) { 450 ViewPropertyAnimatorCompatICS.y(view, value); 451 } 452 453 @Override 454 public void yBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 455 ViewPropertyAnimatorCompatICS.yBy(view, value); 456 } 457 458 @Override 459 public void translationXBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 460 ViewPropertyAnimatorCompatICS.translationXBy(view, value); 461 } 462 463 @Override 464 public void translationYBy(ViewPropertyAnimatorCompat vpa, View view, float value) { 465 ViewPropertyAnimatorCompatICS.translationYBy(view, value); 466 } 467 468 @Override 469 public void start(ViewPropertyAnimatorCompat vpa, View view) { 470 ViewPropertyAnimatorCompatICS.start(view); 471 } 472 473 @Override 474 public void setListener(ViewPropertyAnimatorCompat vpa, View view, ViewPropertyAnimatorListener listener) { 475 view.setTag(LISTENER_TAG_ID, listener); 476 ViewPropertyAnimatorCompatICS.setListener(view, new MyVpaListener(vpa)); 477 } 478 479 @Override 480 public void withEndAction(ViewPropertyAnimatorCompat vpa, View view, final Runnable runnable) { 481 ViewPropertyAnimatorCompatICS.setListener(view, new MyVpaListener(vpa)); 482 vpa.mEndAction = runnable; 483 } 484 485 @Override 486 public void withStartAction(ViewPropertyAnimatorCompat vpa, View view, final Runnable runnable) { 487 ViewPropertyAnimatorCompatICS.setListener(view, new MyVpaListener(vpa)); 488 vpa.mStartAction = runnable; 489 } 490 491 @Override 492 public void withLayer(ViewPropertyAnimatorCompat vpa, View view) { 493 vpa.mOldLayerType = ViewCompat.getLayerType(view); 494 ViewPropertyAnimatorCompatICS.setListener(view, new MyVpaListener(vpa)); 495 } 496 497 static class MyVpaListener implements ViewPropertyAnimatorListener { 498 499 ViewPropertyAnimatorCompat mVpa; 500 501 MyVpaListener(ViewPropertyAnimatorCompat vpa) { 502 mVpa = vpa; 503 } 504 505 @Override 506 public void onAnimationStart(View view) { 507 if (mVpa.mOldLayerType >= 0) { 508 ViewCompat.setLayerType(view, ViewCompat.LAYER_TYPE_HARDWARE, null); 509 } 510 if (mVpa.mStartAction != null) { 511 mVpa.mStartAction.run(); 512 } 513 Object listenerTag = view.getTag(LISTENER_TAG_ID); 514 ViewPropertyAnimatorListener listener = null; 515 if (listenerTag instanceof ViewPropertyAnimatorListener) { 516 listener = (ViewPropertyAnimatorListener) listenerTag; 517 } 518 if (listener != null) { 519 listener.onAnimationStart(view); 520 } 521 } 522 523 @Override 524 public void onAnimationEnd(View view) { 525 if (mVpa.mOldLayerType >= 0) { 526 ViewCompat.setLayerType(view, mVpa.mOldLayerType, null); 527 mVpa.mOldLayerType = -1; 528 } 529 if (mVpa.mEndAction != null) { 530 mVpa.mEndAction.run(); 531 } 532 Object listenerTag = view.getTag(LISTENER_TAG_ID); 533 ViewPropertyAnimatorListener listener = null; 534 if (listenerTag instanceof ViewPropertyAnimatorListener) { 535 listener = (ViewPropertyAnimatorListener) listenerTag; 536 } 537 if (listener != null) { 538 listener.onAnimationEnd(view); 539 } 540 } 541 542 @Override 543 public void onAnimationCancel(View view) { 544 Object listenerTag = view.getTag(LISTENER_TAG_ID); 545 ViewPropertyAnimatorListener listener = null; 546 if (listenerTag instanceof ViewPropertyAnimatorListener) { 547 listener = (ViewPropertyAnimatorListener) listenerTag; 548 } 549 if (listener != null) { 550 listener.onAnimationCancel(view); 551 } 552 } 553 }; 554 } 555 556 static class JBViewPropertyAnimatorCompatImpl extends ICSViewPropertyAnimatorCompatImpl { 557 558 @Override 559 public void setListener(ViewPropertyAnimatorCompat vpa, View view, ViewPropertyAnimatorListener listener) { 560 ViewPropertyAnimatorCompatJB.setListener(view, listener); 561 } 562 563 @Override 564 public void withStartAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable) { 565 ViewPropertyAnimatorCompatJB.withStartAction(view, runnable); 566 } 567 568 @Override 569 public void withEndAction(ViewPropertyAnimatorCompat vpa, View view, Runnable runnable) { 570 ViewPropertyAnimatorCompatJB.withEndAction(view, runnable); 571 } 572 573 @Override 574 public void withLayer(ViewPropertyAnimatorCompat vpa, View view) { 575 ViewPropertyAnimatorCompatJB.withLayer(view); 576 } 577 } 578 579 static class JBMr2ViewPropertyAnimatorCompatImpl extends JBViewPropertyAnimatorCompatImpl { 580 581 @Override 582 public Interpolator getInterpolator(ViewPropertyAnimatorCompat vpa, View view) { 583 return (Interpolator) ViewPropertyAnimatorCompatJellybeanMr2.getInterpolator(view); 584 } 585 } 586 587 static class KitKatViewPropertyAnimatorCompatImpl extends JBMr2ViewPropertyAnimatorCompatImpl { 588 @Override 589 public void setUpdateListener(ViewPropertyAnimatorCompat vpa, View view, ViewPropertyAnimatorUpdateListener listener) { 590 ViewPropertyAnimatorCompatKK.setUpdateListener(view, listener); 591 } 592 } 593 594 static final ViewPropertyAnimatorCompatImpl IMPL; 595 static { 596 final int version = android.os.Build.VERSION.SDK_INT; 597 if (version >= 19) { 598 IMPL = new KitKatViewPropertyAnimatorCompatImpl(); 599 } else if (version >= 18) { 600 IMPL = new JBMr2ViewPropertyAnimatorCompatImpl(); 601 } else if (version >= 16) { 602 IMPL = new JBViewPropertyAnimatorCompatImpl(); 603 } else if (version >= 14) { 604 IMPL = new ICSViewPropertyAnimatorCompatImpl(); 605 } else { 606 IMPL = new BaseViewPropertyAnimatorCompatImpl(); 607 } 608 } 609 610 /** 611 * Sets the duration for the underlying animator that animates the requested properties. 612 * By default, the animator uses the default value for ValueAnimator. Calling this method 613 * will cause the declared value to be used instead. 614 * 615 * <p>Prior to API 14, this method will do nothing.</p> 616 * 617 * @param value The length of ensuing property animations, in milliseconds. The value 618 * cannot be negative. 619 * @return This object, allowing calls to methods in this class to be chained. 620 */ 621 public ViewPropertyAnimatorCompat setDuration(long value) { 622 View view; 623 if ((view = mView.get()) != null) { 624 IMPL.setDuration(this, view, value); 625 } 626 return this; 627 } 628 629 /** 630 * This method will cause the View's <code>alpha</code> property to be animated to the 631 * specified value. Animations already running on the property will be canceled. 632 * 633 * <p>Prior to API 14, this method will do nothing.</p> 634 * 635 * @param value The value to be animated to. 636 * @return This object, allowing calls to methods in this class to be chained. 637 */ 638 public ViewPropertyAnimatorCompat alpha(float value) { 639 View view; 640 if ((view = mView.get()) != null) { 641 IMPL.alpha(this, view, value); 642 } 643 return this; 644 } 645 646 /** 647 * This method will cause the View's <code>alpha</code> property to be animated by the 648 * specified value. Animations already running on the property will be canceled. 649 * 650 * <p>Prior to API 14, this method will do nothing.</p> 651 * 652 * @param value The amount to be animated by, as an offset from the current value. 653 * @return This object, allowing calls to methods in this class to be chained. 654 */ 655 public ViewPropertyAnimatorCompat alphaBy(float value) { 656 View view; 657 if ((view = mView.get()) != null) { 658 IMPL.alphaBy(this, view, value); 659 } 660 return this; 661 } 662 663 /** 664 * This method will cause the View's <code>translationX</code> property to be animated to the 665 * specified value. Animations already running on the property will be canceled. 666 * 667 * <p>Prior to API 14, this method will do nothing.</p> 668 * 669 * @param value The value to be animated to. 670 * @return This object, allowing calls to methods in this class to be chained. 671 */ 672 public ViewPropertyAnimatorCompat translationX(float value) { 673 View view; 674 if ((view = mView.get()) != null) { 675 IMPL.translationX(this, view, value); 676 } 677 return this; 678 } 679 680 /** 681 * This method will cause the View's <code>translationY</code> property to be animated to the 682 * specified value. Animations already running on the property will be canceled. 683 * 684 * <p>Prior to API 14, this method will do nothing.</p> 685 * 686 * @param value The value to be animated to. 687 * @return This object, allowing calls to methods in this class to be chained. 688 */ 689 public ViewPropertyAnimatorCompat translationY(float value) { 690 View view; 691 if ((view = mView.get()) != null) { 692 IMPL.translationY(this, view, value); 693 } 694 return this; 695 } 696 697 /** 698 * Specifies an action to take place when the next animation ends. The action is only 699 * run if the animation ends normally; if the ViewPropertyAnimator is canceled during 700 * that animation, the runnable will not run. 701 * This method, along with {@link #withStartAction(Runnable)}, is intended to help facilitate 702 * choreographing ViewPropertyAnimator animations with other animations or actions 703 * in the application. 704 * 705 * <p>For example, the following code animates a view to x=200 and then back to 0:</p> 706 * <pre> 707 * Runnable endAction = new Runnable() { 708 * public void run() { 709 * view.animate().x(0); 710 * } 711 * }; 712 * view.animate().x(200).withEndAction(endAction); 713 * </pre> 714 * 715 * <p>Prior to API 14, this method will run the action immediately.</p> 716 * 717 * <p>For API 14 and 15, this method will run by setting 718 * a listener on the ViewPropertyAnimatorCompat object and running the action 719 * in that listener's {@link ViewPropertyAnimatorListener#onAnimationEnd(View)} method.</p> 720 * 721 * @param runnable The action to run when the next animation ends. 722 * @return This object, allowing calls to methods in this class to be chained. 723 */ 724 public ViewPropertyAnimatorCompat withEndAction(Runnable runnable) { 725 View view; 726 if ((view = mView.get()) != null) { 727 IMPL.withEndAction(this, view, runnable); 728 } 729 return this; 730 } 731 732 /** 733 * Returns the current duration of property animations. If the duration was set on this 734 * object, that value is returned. Otherwise, the default value of the underlying Animator 735 * is returned. 736 * 737 * <p>Prior to API 14, this method will return 0.</p> 738 * 739 * @see #setDuration(long) 740 * @return The duration of animations, in milliseconds. 741 */ 742 public long getDuration() { 743 View view; 744 if ((view = mView.get()) != null) { 745 return IMPL.getDuration(this, view); 746 } else { 747 return 0; 748 } 749 } 750 751 /** 752 * Sets the interpolator for the underlying animator that animates the requested properties. 753 * By default, the animator uses the default interpolator for ValueAnimator. Calling this method 754 * will cause the declared object to be used instead. 755 * 756 * <p>Prior to API 14, this method will do nothing.</p> 757 * 758 * @param value The TimeInterpolator to be used for ensuing property animations. 759 * @return This object, allowing calls to methods in this class to be chained. 760 */ 761 public ViewPropertyAnimatorCompat setInterpolator(Interpolator value) { 762 View view; 763 if ((view = mView.get()) != null) { 764 IMPL.setInterpolator(this, view, value); 765 } 766 return this; 767 } 768 769 /** 770 * Returns the timing interpolator that this animation uses. 771 * 772 * <p>Prior to API 14, this method will return null.</p> 773 * 774 * @return The timing interpolator for this animation. 775 */ 776 public Interpolator getInterpolator() { 777 View view; 778 if ((view = mView.get()) != null) { 779 return IMPL.getInterpolator(this, view); 780 } 781 else return null; 782 } 783 784 /** 785 * Sets the startDelay for the underlying animator that animates the requested properties. 786 * By default, the animator uses the default value for ValueAnimator. Calling this method 787 * will cause the declared value to be used instead. 788 * 789 * <p>Prior to API 14, this method will do nothing.</p> 790 * 791 * @param value The delay of ensuing property animations, in milliseconds. The value 792 * cannot be negative. 793 * @return This object, allowing calls to methods in this class to be chained. 794 */ 795 public ViewPropertyAnimatorCompat setStartDelay(long value) { 796 View view; 797 if ((view = mView.get()) != null) { 798 IMPL.setStartDelay(this, view, value); 799 } 800 return this; 801 } 802 803 /** 804 * Returns the current startDelay of property animations. If the startDelay was set on this 805 * object, that value is returned. Otherwise, the default value of the underlying Animator 806 * is returned. 807 * 808 * <p>Prior to API 14, this method will return 0.</p> 809 * 810 * @see #setStartDelay(long) 811 * @return The startDelay of animations, in milliseconds. 812 */ 813 public long getStartDelay() { 814 View view; 815 if ((view = mView.get()) != null) { 816 return IMPL.getStartDelay(this, view); 817 } else { 818 return 0; 819 } 820 } 821 822 /** 823 * This method will cause the View's <code>rotation</code> property to be animated to the 824 * specified value. Animations already running on the property will be canceled. 825 * 826 * <p>Prior to API 14, this method will do nothing.</p> 827 * 828 * @param value The value to be animated to. 829 * @return This object, allowing calls to methods in this class to be chained. 830 */ 831 public ViewPropertyAnimatorCompat rotation(float value) { 832 View view; 833 if ((view = mView.get()) != null) { 834 IMPL.rotation(this, view, value); 835 } 836 return this; 837 } 838 839 /** 840 * This method will cause the View's <code>rotation</code> property to be animated by the 841 * specified value. Animations already running on the property will be canceled. 842 * 843 * <p>Prior to API 14, this method will do nothing.</p> 844 * 845 * @param value The amount to be animated by, as an offset from the current value. 846 * @return This object, allowing calls to methods in this class to be chained. 847 */ 848 public ViewPropertyAnimatorCompat rotationBy(float value) { 849 View view; 850 if ((view = mView.get()) != null) { 851 IMPL.rotationBy(this, view, value); 852 } 853 return this; 854 } 855 856 /** 857 * This method will cause the View's <code>rotationX</code> property to be animated to the 858 * specified value. Animations already running on the property will be canceled. 859 * 860 * <p>Prior to API 14, this method will do nothing.</p> 861 * 862 * @param value The value to be animated to. 863 * @return This object, allowing calls to methods in this class to be chained. 864 */ 865 public ViewPropertyAnimatorCompat rotationX(float value) { 866 View view; 867 if ((view = mView.get()) != null) { 868 IMPL.rotationX(this, view, value); 869 } 870 return this; 871 } 872 873 /** 874 * This method will cause the View's <code>rotationX</code> property to be animated by the 875 * specified value. Animations already running on the property will be canceled. 876 * 877 * <p>Prior to API 14, this method will do nothing.</p> 878 * 879 * @param value The amount to be animated by, as an offset from the current value. 880 * @return This object, allowing calls to methods in this class to be chained. 881 */ 882 public ViewPropertyAnimatorCompat rotationXBy(float value) { 883 View view; 884 if ((view = mView.get()) != null) { 885 IMPL.rotationXBy(this, view, value); 886 } 887 return this; 888 } 889 890 /** 891 * This method will cause the View's <code>rotationY</code> property to be animated to the 892 * specified value. Animations already running on the property will be canceled. 893 * 894 * <p>Prior to API 14, this method will do nothing.</p> 895 * 896 * @param value The value to be animated to. 897 * @return This object, allowing calls to methods in this class to be chained. 898 */ 899 public ViewPropertyAnimatorCompat rotationY(float value) { 900 View view; 901 if ((view = mView.get()) != null) { 902 IMPL.rotationY(this, view, value); 903 } 904 return this; 905 } 906 907 /** 908 * This method will cause the View's <code>rotationY</code> property to be animated by the 909 * specified value. Animations already running on the property will be canceled. 910 * 911 * <p>Prior to API 14, this method will do nothing.</p> 912 * 913 * @param value The amount to be animated by, as an offset from the current value. 914 * @return This object, allowing calls to methods in this class to be chained. 915 */ 916 public ViewPropertyAnimatorCompat rotationYBy(float value) { 917 View view; 918 if ((view = mView.get()) != null) { 919 IMPL.rotationYBy(this, view, value); 920 } 921 return this; 922 } 923 924 /** 925 * This method will cause the View's <code>scaleX</code> property to be animated to the 926 * specified value. Animations already running on the property will be canceled. 927 * 928 * <p>Prior to API 14, this method will do nothing.</p> 929 * 930 * @param value The value to be animated to. 931 * @return This object, allowing calls to methods in this class to be chained. 932 */ 933 public ViewPropertyAnimatorCompat scaleX(float value) { 934 View view; 935 if ((view = mView.get()) != null) { 936 IMPL.scaleX(this, view, value); 937 } 938 return this; 939 } 940 941 /** 942 * This method will cause the View's <code>scaleX</code> property to be animated by the 943 * specified value. Animations already running on the property will be canceled. 944 * 945 * <p>Prior to API 14, this method will do nothing.</p> 946 * 947 * @param value The amount to be animated by, as an offset from the current value. 948 * @return This object, allowing calls to methods in this class to be chained. 949 */ 950 public ViewPropertyAnimatorCompat scaleXBy(float value) { 951 View view; 952 if ((view = mView.get()) != null) { 953 IMPL.scaleXBy(this, view, value); 954 } 955 return this; 956 } 957 958 /** 959 * This method will cause the View's <code>scaleY</code> property to be animated to the 960 * specified value. Animations already running on the property will be canceled. 961 * 962 * <p>Prior to API 14, this method will do nothing.</p> 963 * 964 * @param value The value to be animated to. 965 * @return This object, allowing calls to methods in this class to be chained. 966 */ 967 public ViewPropertyAnimatorCompat scaleY(float value) { 968 View view; 969 if ((view = mView.get()) != null) { 970 IMPL.scaleY(this, view, value); 971 } 972 return this; 973 } 974 975 /** 976 * This method will cause the View's <code>scaleY</code> property to be animated by the 977 * specified value. Animations already running on the property will be canceled. 978 * 979 * <p>Prior to API 14, this method will do nothing.</p> 980 * 981 * @param value The amount to be animated by, as an offset from the current value. 982 * @return This object, allowing calls to methods in this class to be chained. 983 */ 984 public ViewPropertyAnimatorCompat scaleYBy(float value) { 985 View view; 986 if ((view = mView.get()) != null) { 987 IMPL.scaleYBy(this, view, value); 988 } 989 return this; 990 } 991 992 /** 993 * Cancels all property animations that are currently running or pending. 994 */ 995 public void cancel() { 996 View view; 997 if ((view = mView.get()) != null) { 998 IMPL.cancel(this, view); 999 } 1000 } 1001 1002 /** 1003 * This method will cause the View's <code>x</code> property to be animated to the 1004 * specified value. Animations already running on the property will be canceled. 1005 * 1006 * <p>Prior to API 14, this method will do nothing.</p> 1007 * 1008 * @param value The value to be animated to. 1009 * @return This object, allowing calls to methods in this class to be chained. 1010 */ 1011 public ViewPropertyAnimatorCompat x(float value) { 1012 View view; 1013 if ((view = mView.get()) != null) { 1014 IMPL.x(this, view, value); 1015 } 1016 return this; 1017 } 1018 1019 /** 1020 * This method will cause the View's <code>x</code> property to be animated by the 1021 * specified value. Animations already running on the property will be canceled. 1022 * 1023 * <p>Prior to API 14, this method will do nothing.</p> 1024 * 1025 * @param value The amount to be animated by, as an offset from the current value. 1026 * @return This object, allowing calls to methods in this class to be chained. 1027 */ 1028 public ViewPropertyAnimatorCompat xBy(float value) { 1029 View view; 1030 if ((view = mView.get()) != null) { 1031 IMPL.xBy(this, view, value); 1032 } 1033 return this; 1034 } 1035 1036 /** 1037 * This method will cause the View's <code>y</code> property to be animated to the 1038 * specified value. Animations already running on the property will be canceled. 1039 * 1040 * <p>Prior to API 14, this method will do nothing.</p> 1041 * 1042 * @param value The value to be animated to. 1043 * @return This object, allowing calls to methods in this class to be chained. 1044 */ 1045 public ViewPropertyAnimatorCompat y(float value) { 1046 View view; 1047 if ((view = mView.get()) != null) { 1048 IMPL.y(this, view, value); 1049 } 1050 return this; 1051 } 1052 1053 /** 1054 * This method will cause the View's <code>y</code> property to be animated by the 1055 * specified value. Animations already running on the property will be canceled. 1056 * 1057 * <p>Prior to API 14, this method will do nothing.</p> 1058 * 1059 * @param value The amount to be animated by, as an offset from the current value. 1060 * @return This object, allowing calls to methods in this class to be chained. 1061 */ 1062 public ViewPropertyAnimatorCompat yBy(float value) { 1063 View view; 1064 if ((view = mView.get()) != null) { 1065 IMPL.yBy(this, view, value); 1066 } 1067 return this; 1068 } 1069 1070 /** 1071 * This method will cause the View's <code>translationX</code> property to be animated by the 1072 * specified value. Animations already running on the property will be canceled. 1073 * 1074 * <p>Prior to API 14, this method will do nothing.</p> 1075 * 1076 * @param value The amount to be animated by, as an offset from the current value. 1077 * @return This object, allowing calls to methods in this class to be chained. 1078 */ 1079 public ViewPropertyAnimatorCompat translationXBy(float value) { 1080 View view; 1081 if ((view = mView.get()) != null) { 1082 IMPL.translationXBy(this, view, value); 1083 } 1084 return this; 1085 } 1086 1087 /** 1088 * This method will cause the View's <code>translationY</code> property to be animated by the 1089 * specified value. Animations already running on the property will be canceled. 1090 * 1091 * <p>Prior to API 14, this method will do nothing.</p> 1092 * 1093 * @param value The amount to be animated by, as an offset from the current value. 1094 * @return This object, allowing calls to methods in this class to be chained. 1095 */ 1096 public ViewPropertyAnimatorCompat translationYBy(float value) { 1097 View view; 1098 if ((view = mView.get()) != null) { 1099 IMPL.translationYBy(this, view, value); 1100 } 1101 return this; 1102 } 1103 1104 /** 1105 * Starts the currently pending property animations immediately. Calling <code>start()</code> 1106 * is optional because all animations start automatically at the next opportunity. However, 1107 * if the animations are needed to start immediately and synchronously (not at the time when 1108 * the next event is processed by the hierarchy, which is when the animations would begin 1109 * otherwise), then this method can be used. 1110 * 1111 * <p>Prior to API 14, this method will do nothing.</p> 1112 */ 1113 public void start() { 1114 View view; 1115 if ((view = mView.get()) != null) { 1116 IMPL.start(this, view); 1117 } 1118 } 1119 1120 /** 1121 * The View associated with this ViewPropertyAnimator will have its 1122 * {@link ViewCompat#setLayerType(View, int, android.graphics.Paint) layer type} set to 1123 * {@link ViewCompat#LAYER_TYPE_HARDWARE} for the duration of the next animation. 1124 * As stated in the documentation for {@link ViewCompat#LAYER_TYPE_HARDWARE}, 1125 * the actual type of layer used internally depends on the runtime situation of the 1126 * view. If the activity and this view are hardware-accelerated, then the layer will be 1127 * accelerated as well. If the activity or the view is not accelerated, then the layer will 1128 * effectively be the same as {@link ViewCompat#LAYER_TYPE_SOFTWARE}. 1129 * 1130 * <p>This state is not persistent, either on the View or on this ViewPropertyAnimator: the 1131 * layer type of the View will be restored when the animation ends to what it was when this 1132 * method was called, and this setting on ViewPropertyAnimator is only valid for the next 1133 * animation. Note that calling this method and then independently setting the layer type of 1134 * the View (by a direct call to 1135 * {@link ViewCompat#setLayerType(View, int, android.graphics.Paint)}) will result in some 1136 * inconsistency, including having the layer type restored to its pre-withLayer() 1137 * value when the animation ends.</p> 1138 * 1139 * <p>Prior to API 14, this method will do nothing.</p> 1140 * 1141 * <p>For API 14 and 15, this method will run by setting 1142 * a listener on the ViewPropertyAnimatorCompat object, setting a hardware layer in 1143 * the listener's {@link ViewPropertyAnimatorListener#onAnimationStart(View)} method, 1144 * and then restoring the orignal layer type in the listener's 1145 * {@link ViewPropertyAnimatorListener#onAnimationEnd(View)} method.</p> 1146 * 1147 * @see View#setLayerType(int, android.graphics.Paint) 1148 * @return This object, allowing calls to methods in this class to be chained. 1149 */ 1150 public ViewPropertyAnimatorCompat withLayer() { 1151 View view; 1152 if ((view = mView.get()) != null) { 1153 IMPL.withLayer(this, view); 1154 } 1155 return this; 1156 } 1157 1158 /** 1159 * Specifies an action to take place when the next animation runs. If there is a 1160 * {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the 1161 * action will run after that startDelay expires, when the actual animation begins. 1162 * This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate 1163 * choreographing ViewPropertyAnimator animations with other animations or actions 1164 * in the application. 1165 * 1166 * <p>Prior to API 14, this method will run the action immediately.</p> 1167 * 1168 * <p>For API 14 and 15, this method will run by setting 1169 * a listener on the ViewPropertyAnimatorCompat object and running the action 1170 * in that listener's {@link ViewPropertyAnimatorListener#onAnimationStart(View)} method.</p> 1171 * 1172 * @param runnable The action to run when the next animation starts. 1173 * @return This object, allowing calls to methods in this class to be chained. 1174 */ 1175 public ViewPropertyAnimatorCompat withStartAction(Runnable runnable) { 1176 View view; 1177 if ((view = mView.get()) != null) { 1178 IMPL.withStartAction(this, view, runnable); 1179 } 1180 return this; 1181 } 1182 1183 /** 1184 * Sets a listener for events in the underlying Animators that run the property 1185 * animations. 1186 * 1187 * <p>Prior to API 14, this method will do nothing.</p> 1188 * 1189 * @param listener The listener to be called with AnimatorListener events. A value of 1190 * <code>null</code> removes any existing listener. 1191 * @return This object, allowing calls to methods in this class to be chained. 1192 */ 1193 public ViewPropertyAnimatorCompat setListener(ViewPropertyAnimatorListener listener) { 1194 View view; 1195 if ((view = mView.get()) != null) { 1196 IMPL.setListener(this, view, listener); 1197 } 1198 return this; 1199 } 1200 1201 /** 1202 * Sets a listener for update events in the underlying Animator that runs 1203 * the property animations. 1204 * 1205 * <p>Prior to API 19, this method will do nothing.</p> 1206 * 1207 * @param listener The listener to be called with update events. A value of 1208 * <code>null</code> removes any existing listener. 1209 * @return This object, allowing calls to methods in this class to be chained. 1210 */ 1211 public ViewPropertyAnimatorCompat setUpdateListener( 1212 ViewPropertyAnimatorUpdateListener listener) { 1213 View view; 1214 if ((view = mView.get()) != null) { 1215 IMPL.setUpdateListener(this, view, listener); 1216 } 1217 return this; 1218 } 1219} 1220