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