1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/*
2d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Copyright (C) 2014 The Android Open Source Project
3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License.
6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at
7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software
11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and
14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License.
15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */
16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepackage android.support.v4.view;
17d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
18a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikasimport android.animation.Animator;
19a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikasimport android.animation.AnimatorListenerAdapter;
20a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikasimport android.animation.ValueAnimator;
21bfd48d0521963754e04e407499ee9e278fe06c0fChris Banesimport android.os.Build;
22d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View;
23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.animation.Interpolator;
24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
25d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.lang.ref.WeakReference;
26d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
27c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class ViewPropertyAnimatorCompat {
28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private static final String TAG = "ViewAnimatorCompat";
29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private WeakReference<View> mView;
30552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas    Runnable mStartAction = null;
31552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas    Runnable mEndAction = null;
32552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas    int mOldLayerType = -1;
33ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase    // HACK ALERT! Choosing this id knowing that the framework does not use it anywhere
34ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase    // internally and apps should use ids higher than it
35ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase    static final int LISTENER_TAG_ID = 0x7e000000;
36ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase
37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    ViewPropertyAnimatorCompat(View view) {
38d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        mView = new WeakReference<View>(view);
39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
40d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
41a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas    static class ViewPropertyAnimatorListenerApi14 implements ViewPropertyAnimatorListener {
42a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        ViewPropertyAnimatorCompat mVpa;
43a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        boolean mAnimEndCalled;
44d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
45a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        ViewPropertyAnimatorListenerApi14(ViewPropertyAnimatorCompat vpa) {
46a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            mVpa = vpa;
47d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
48d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
49d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        @Override
50a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        public void onAnimationStart(View view) {
51a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            // Reset our end called flag, since this is a new animation...
52a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            mAnimEndCalled = false;
53e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
54a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (mVpa.mOldLayerType > -1) {
55a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
56a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
57a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (mVpa.mStartAction != null) {
58a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                Runnable startAction = mVpa.mStartAction;
59a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mVpa.mStartAction = null;
60a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                startAction.run();
61a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
62a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            Object listenerTag = view.getTag(LISTENER_TAG_ID);
63a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            ViewPropertyAnimatorListener listener = null;
64a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (listenerTag instanceof ViewPropertyAnimatorListener) {
65a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                listener = (ViewPropertyAnimatorListener) listenerTag;
66a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
67a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (listener != null) {
68a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                listener.onAnimationStart(view);
69a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
70e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        }
71e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
72e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        @Override
73a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        public void onAnimationEnd(View view) {
74a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (mVpa.mOldLayerType > -1) {
75a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.setLayerType(mVpa.mOldLayerType, null);
76a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mVpa.mOldLayerType = -1;
77ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase            }
78a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 16 || !mAnimEndCalled) {
79a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                // Pre-v16 seems to have a bug where onAnimationEnd is called
80a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                // twice, therefore we only dispatch on the first call
81a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                if (mVpa.mEndAction != null) {
82a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    Runnable endAction = mVpa.mEndAction;
83a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    mVpa.mEndAction = null;
84a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    endAction.run();
85ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase                }
86ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase                Object listenerTag = view.getTag(LISTENER_TAG_ID);
87ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase                ViewPropertyAnimatorListener listener = null;
88ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase                if (listenerTag instanceof ViewPropertyAnimatorListener) {
89ead7065c8e987fefca4d0d850d824fb7d7bce677Chet Haase                    listener = (ViewPropertyAnimatorListener) listenerTag;
90797c82a7055f7ba825169388465617f0db716739Chet Haase                }
91797c82a7055f7ba825169388465617f0db716739Chet Haase                if (listener != null) {
92a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    listener.onAnimationEnd(view);
93797c82a7055f7ba825169388465617f0db716739Chet Haase                }
94a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mAnimEndCalled = true;
95797c82a7055f7ba825169388465617f0db716739Chet Haase            }
96d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
97d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
98d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        @Override
99a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        public void onAnimationCancel(View view) {
100a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            Object listenerTag = view.getTag(LISTENER_TAG_ID);
101a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            ViewPropertyAnimatorListener listener = null;
102a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (listenerTag instanceof ViewPropertyAnimatorListener) {
103a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                listener = (ViewPropertyAnimatorListener) listenerTag;
104a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
105a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (listener != null) {
106a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                listener.onAnimationCancel(view);
107a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
108d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
109d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
112d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Sets the duration for the underlying animator that animates the requested properties.
113d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * By default, the animator uses the default value for ValueAnimator. Calling this method
114d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * will cause the declared value to be used instead.
115d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
116d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The length of ensuing property animations, in milliseconds. The value
117d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * cannot be negative.
118d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
119d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
120d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat setDuration(long value) {
121d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
122d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
123846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().setDuration(value);
124d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
125d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
126d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
127d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
128d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
129d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>alpha</code> property to be animated to the
130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
133d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
134d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
135d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat alpha(float value) {
136d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
137d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
138846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().alpha(value);
139d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
140d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
141d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
142d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
143d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
144d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>alpha</code> property to be animated by the
145d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
146d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
147d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
148d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
149d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
150d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat alphaBy(float value) {
151d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
152d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
153846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().alphaBy(value);
154d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
155d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
156d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
157d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
158d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
159d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>translationX</code> property to be animated to the
160d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
161d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
162d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
163d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
164d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
165d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat translationX(float value) {
166d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
167d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
168846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().translationX(value);
169d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
170d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
171d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
172d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
173d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
174d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>translationY</code> property to be animated to the
175d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
176d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
177d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
178d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
179d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
180d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat translationY(float value) {
181d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
182d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
183846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().translationY(value);
184d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
187d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
188d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Specifies an action to take place when the next animation ends. The action is only
190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * run if the animation ends normally; if the ViewPropertyAnimator is canceled during
191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * that animation, the runnable will not run.
192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method, along with {@link #withStartAction(Runnable)}, is intended to help facilitate
193d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
194d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * in the application.
195d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
196d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <p>For example, the following code animates a view to x=200 and then back to 0:</p>
197d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <pre>
198d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *     Runnable endAction = new Runnable() {
199d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *         public void run() {
200d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *             view.animate().x(0);
201d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *         }
202d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *     };
203d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *     view.animate().x(200).withEndAction(endAction);
204d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * </pre>
205d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
206d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <p>For API 14 and 15, this method will run by setting
207d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * a listener on the ViewPropertyAnimatorCompat object and running the action
208d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * in that listener's {@link ViewPropertyAnimatorListener#onAnimationEnd(View)} method.</p>
209d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
210d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param runnable The action to run when the next animation ends.
211d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
212d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
213d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat withEndAction(Runnable runnable) {
214d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
215d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
216a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 16) {
217a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().withEndAction(runnable);
218a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            } else {
219a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                setListenerInternal(view, new ViewPropertyAnimatorListenerApi14(this));
220a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mEndAction = runnable;
221a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
222d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
223d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
224d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
225d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
226d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
227d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Returns the current duration of property animations. If the duration was set on this
228d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * object, that value is returned. Otherwise, the default value of the underlying Animator
229d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * is returned.
230d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
231d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @see #setDuration(long)
232d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return The duration of animations, in milliseconds.
233d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
234d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public long getDuration() {
235d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
236d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
237846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            return view.animate().getDuration();
238d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        } else {
239d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            return 0;
240d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
241d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
242d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
243d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Sets the interpolator for the underlying animator that animates the requested properties.
245d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * By default, the animator uses the default interpolator for ValueAnimator. Calling this method
246d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * will cause the declared object to be used instead.
247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The TimeInterpolator to be used for ensuing property animations.
249d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
250d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
251d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat setInterpolator(Interpolator value) {
252d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
253d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
254846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().setInterpolator(value);
255d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
256d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
257d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
258d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
259d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
260d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Returns the timing interpolator that this animation uses.
261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return The timing interpolator for this animation.
263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public Interpolator getInterpolator() {
265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
267a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 18) {
268a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                return (Interpolator) view.animate().getInterpolator();
269a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
270d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
271a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        return null;
272d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
273d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
274d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
275d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Sets the startDelay for the underlying animator that animates the requested properties.
276d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * By default, the animator uses the default value for ValueAnimator. Calling this method
277d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * will cause the declared value to be used instead.
278d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
279d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The delay of ensuing property animations, in milliseconds. The value
280d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * cannot be negative.
281d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
282d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
283d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat setStartDelay(long value) {
284d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
285d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
286846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().setStartDelay(value);
287d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
288d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
289d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
290d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
291d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
292d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Returns the current startDelay of property animations. If the startDelay was set on this
293d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * object, that value is returned. Otherwise, the default value of the underlying Animator
294d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * is returned.
295d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
296d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @see #setStartDelay(long)
297d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return The startDelay of animations, in milliseconds.
298d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
299d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public long getStartDelay() {
300d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
301d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
302846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            return view.animate().getStartDelay();
303d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        } else {
304d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            return 0;
305d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
306d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
307d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
308d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
309d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotation</code> property to be animated to the
310d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
311d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
312d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
313d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
314d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
315d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotation(float value) {
316d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
317d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
318846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotation(value);
319d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
320d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
321d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
322d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
323d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
324d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotation</code> property to be animated by the
325d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
326d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
327d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
328d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
329d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
330d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotationBy(float value) {
331d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
332d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
333846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotationBy(value);
334d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
335d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
336d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
337d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
338d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
339d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated to the
340d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
341d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
342d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
343d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
344d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
345d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotationX(float value) {
346d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
347d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
348846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotationX(value);
349d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
350d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
351d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
352d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
353d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
354d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated by the
355d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
356d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
357d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
358d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
359d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
360d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotationXBy(float value) {
361d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
362d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
363846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotationXBy(value);
364d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
365d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
366d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
367d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
368d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
369d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated to the
370d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
371d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
372d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
373d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
374d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
375d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotationY(float value) {
376d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
377d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
378846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotationY(value);
379d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
380d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
381d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
382d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
383d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
384d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated by the
385d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
386d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
387d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
388d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
389d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
390d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat rotationYBy(float value) {
391d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
392d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
393846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().rotationYBy(value);
394d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
395d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
396d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
397d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
398d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
399d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated to the
400d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
401d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
402d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
403d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
404d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
405d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat scaleX(float value) {
406d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
407d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
408846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().scaleX(value);
409d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
410d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
411d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
412d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
413d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
414d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated by the
415d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
416d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
417d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
418d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
419d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
420d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat scaleXBy(float value) {
421d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
422d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
423846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().scaleXBy(value);
424d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
425d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
426d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
427d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
428d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
429d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated to the
430d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
431d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
432d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
433d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
434d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
435d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat scaleY(float value) {
436d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
437d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
438846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().scaleY(value);
439d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
440d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
441d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
442d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
443d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
444d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated by the
445d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
446d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
447d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
448d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
449d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
450d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat scaleYBy(float value) {
451d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
452d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
453846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().scaleYBy(value);
454d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
455d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
456d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
457d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
458d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
459d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Cancels all property animations that are currently running or pending.
460d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
461d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public void cancel() {
462d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
463d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
464846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().cancel();
465d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
466d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
467d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
468d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
469d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>x</code> property to be animated to the
470d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
471d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
472d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
473d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
474d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
475d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat x(float value) {
476d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
477d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
478846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().x(value);
479d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
480d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
481d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
482d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
483d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
484d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>x</code> property to be animated by the
485d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
486d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
487d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
488d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
489d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
490d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat xBy(float value) {
491d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
492d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
493846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().xBy(value);
494d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
495d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
496d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
497d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
498d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
499d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>y</code> property to be animated to the
500d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
501d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
502d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The value to be animated to.
503d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
504d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
505d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat y(float value) {
506d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
507d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
508846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().y(value);
509d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
510d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
511d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
512d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
513d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
514d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>y</code> property to be animated by the
515d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
516d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
517d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
518d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
519d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
520d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat yBy(float value) {
521d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
522d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
523846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().yBy(value);
524d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
525d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
526d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
527d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
528d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
529d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>translationX</code> property to be animated by the
530d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
531d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
532d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
533d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
534d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
535d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat translationXBy(float value) {
536d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
537d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
538846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().translationXBy(value);
539d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
540d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
541d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
542d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
543d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
544d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method will cause the View's <code>translationY</code> property to be animated by the
545d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * specified value. Animations already running on the property will be canceled.
546d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
547d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param value The amount to be animated by, as an offset from the current value.
548d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
549d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
550d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat translationYBy(float value) {
551d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
552d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
553846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().translationYBy(value);
554d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
555d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
556d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
557d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
558d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
559e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * This method will cause the View's <code>translationZ</code> property to be animated by the
560e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * specified value. Animations already running on the property will be canceled.
561e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
562e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * <p>Prior to API 21, this method will do nothing.</p>
563e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
564e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @param value The amount to be animated by, as an offset from the current value.
565e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @return This object, allowing calls to methods in this class to be chained.
566e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     */
567e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    public ViewPropertyAnimatorCompat translationZBy(float value) {
568e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        View view;
569e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        if ((view = mView.get()) != null) {
570a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 21) {
571a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().translationZBy(value);
572a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
573e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        }
574e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        return this;
575e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    }
576e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
577e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    /**
578e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * This method will cause the View's <code>translationZ</code> property to be animated to the
579e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * specified value. Animations already running on the property will be canceled.
580e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
581e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * <p>Prior to API 21, this method will do nothing.</p>
582e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
583e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @param value The amount to be animated by, as an offset from the current value.
584e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @return This object, allowing calls to methods in this class to be chained.
585e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     */
586e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    public ViewPropertyAnimatorCompat translationZ(float value) {
587e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        View view;
588e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        if ((view = mView.get()) != null) {
589a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 21) {
590a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().translationZ(value);
591a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
592e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        }
593e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        return this;
594e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    }
595e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
596e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    /**
597e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * This method will cause the View's <code>z</code> property to be animated to the
598e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * specified value. Animations already running on the property will be canceled.
599e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
600e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * <p>Prior to API 21, this method will do nothing.</p>
601e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
602e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @param value The amount to be animated by, as an offset from the current value.
603e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @return This object, allowing calls to methods in this class to be chained.
604e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     */
605e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    public ViewPropertyAnimatorCompat z(float value) {
606e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        View view;
607e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        if ((view = mView.get()) != null) {
608a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 21) {
609a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().z(value);
610a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
611e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        }
612e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        return this;
613e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    }
614e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
615e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    /**
616e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * This method will cause the View's <code>z</code> property to be animated by the
617e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * specified value. Animations already running on the property will be canceled.
618e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
619e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * <p>Prior to API 21, this method will do nothing.</p>
620e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     *
621e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @param value The amount to be animated by, as an offset from the current value.
622e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     * @return This object, allowing calls to methods in this class to be chained.
623e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes     */
624e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    public ViewPropertyAnimatorCompat zBy(float value) {
625e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        View view;
626e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        if ((view = mView.get()) != null) {
627a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 21) {
628a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().zBy(value);
629a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
630e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        }
631e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes        return this;
632e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    }
633e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes
634e322b8bcc717dfd663677ed5cb59c6d1c3cb27afChris Banes    /**
635d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Starts the currently pending property animations immediately. Calling <code>start()</code>
636d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * is optional because all animations start automatically at the next opportunity. However,
637d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * if the animations are needed to start immediately and synchronously (not at the time when
638d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * the next event is processed by the hierarchy, which is when the animations would begin
639d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * otherwise), then this method can be used.
640d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
641d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public void start() {
642d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
643d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
644846955fba824b96d8cca48e372353d5b7cc31955Aurimas Liutikas            view.animate().start();
645d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
646d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
647d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
648d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
649d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * The View associated with this ViewPropertyAnimator will have its
650fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas     * {@link View#setLayerType(int, android.graphics.Paint) layer type} set to
651fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas     * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation.
652fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas     * As stated in the documentation for {@link View#LAYER_TYPE_HARDWARE},
653d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * the actual type of layer used internally depends on the runtime situation of the
654d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * view. If the activity and this view are hardware-accelerated, then the layer will be
655d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * accelerated as well. If the activity or the view is not accelerated, then the layer will
656fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas     * effectively be the same as {@link View#LAYER_TYPE_SOFTWARE}.
657d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
658d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <p>This state is not persistent, either on the View or on this ViewPropertyAnimator: the
659d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * layer type of the View will be restored when the animation ends to what it was when this
660d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * method was called, and this setting on ViewPropertyAnimator is only valid for the next
661d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * animation. Note that calling this method and then independently setting the layer type of
662d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * the View (by a direct call to
663fa0f82f629bf95681c14ed559922f77a3030aa18Aurimas Liutikas     * {@link View#setLayerType(int, android.graphics.Paint)}) will result in some
664d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * inconsistency, including having the layer type restored to its pre-withLayer()
665d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * value when the animation ends.</p>
666d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
667d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <p>For API 14 and 15, this method will run by setting
668d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * a listener on the ViewPropertyAnimatorCompat object, setting a hardware layer in
669d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * the listener's {@link ViewPropertyAnimatorListener#onAnimationStart(View)} method,
670d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * and then restoring the orignal layer type in the listener's
671d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * {@link ViewPropertyAnimatorListener#onAnimationEnd(View)} method.</p>
672d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
673d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @see View#setLayerType(int, android.graphics.Paint)
674d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
675d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
676d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat withLayer() {
677d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
678d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
679a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 16) {
680a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().withLayer();
681a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            } else {
682a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mOldLayerType = view.getLayerType();
683a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                setListenerInternal(view, new ViewPropertyAnimatorListenerApi14(this));
684a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
685d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
686d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
687d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
688d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
689d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
690d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Specifies an action to take place when the next animation runs. If there is a
691d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the
692d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * action will run after that startDelay expires, when the actual animation begins.
693d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate
694d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
695d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * in the application.
696d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
697d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <p>For API 14 and 15, this method will run by setting
698d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * a listener on the ViewPropertyAnimatorCompat object and running the action
699d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * in that listener's {@link ViewPropertyAnimatorListener#onAnimationStart(View)} method.</p>
700d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
701d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param runnable The action to run when the next animation starts.
702d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
703d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
704d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public ViewPropertyAnimatorCompat withStartAction(Runnable runnable) {
705d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        View view;
706d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
707a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 16) {
708a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().withStartAction(runnable);
709a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            } else {
710a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                setListenerInternal(view, new ViewPropertyAnimatorListenerApi14(this));
711a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                mStartAction = runnable;
712a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
713d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
714d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
715d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
716d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
717d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
718d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Sets a listener for events in the underlying Animators that run the property
719d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * animations.
720d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     *
721d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @param listener The listener to be called with AnimatorListener events. A value of
722d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * <code>null</code> removes any existing listener.
723d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * @return This object, allowing calls to methods in this class to be chained.
724d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
725a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas    public ViewPropertyAnimatorCompat setListener(final ViewPropertyAnimatorListener listener) {
726a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        final View view;
727d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if ((view = mView.get()) != null) {
728a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 16) {
729a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                setListenerInternal(view, listener);
730a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            } else {
731a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.setTag(LISTENER_TAG_ID, listener);
732a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                setListenerInternal(view, new ViewPropertyAnimatorListenerApi14(this));
733a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
734d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
735d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return this;
736d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
73749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
738a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas    private void setListenerInternal(final View view, final ViewPropertyAnimatorListener listener) {
739a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        if (listener != null) {
740a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            view.animate().setListener(new AnimatorListenerAdapter() {
741a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                @Override
742a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                public void onAnimationCancel(Animator animation) {
743a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    listener.onAnimationCancel(view);
744a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                }
745a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas
746a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                @Override
747a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                public void onAnimationEnd(Animator animation) {
748a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    listener.onAnimationEnd(view);
749a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                }
750a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas
751a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                @Override
752a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                public void onAnimationStart(Animator animation) {
753a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    listener.onAnimationStart(view);
754a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                }
755a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            });
756a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        } else {
757a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            view.animate().setListener(null);
758a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        }
759a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas    }
760a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas
76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
76249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets a listener for update events in the underlying Animator that runs
76349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the property animations.
76449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
76549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>Prior to API 19, this method will do nothing.</p>
76649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
76749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param listener The listener to be called with update events. A value of
76849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <code>null</code> removes any existing listener.
76949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return This object, allowing calls to methods in this class to be chained.
77049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
77149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ViewPropertyAnimatorCompat setUpdateListener(
772a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            final ViewPropertyAnimatorUpdateListener listener) {
773a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas        final View view;
77449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if ((view = mView.get()) != null) {
775a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            if (Build.VERSION.SDK_INT >= 19) {
776a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                ValueAnimator.AnimatorUpdateListener wrapped = null;
777a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                if (listener != null) {
778a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    wrapped = new ValueAnimator.AnimatorUpdateListener() {
779a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                        @Override
780a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
781a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                            listener.onAnimationUpdate(view);
782a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                        }
783a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                    };
784a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                }
785a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas                view.animate().setUpdateListener(wrapped);
786a6b67f8cbb80323786f7e5d9db442f080e242d76Aurimas Liutikas            }
78749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
78849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return this;
78949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
790d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase}
791