ViewPropertyAnimator.java revision c1ca665827f0c34419a55c005254c1aaa0d58b40
1a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase/*
2d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase * Copyright (C) 2011 The Android Open Source Project
3a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
4a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * you may not use this file except in compliance with the License.
6a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * You may obtain a copy of the License at
7a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
8a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
10a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * Unless required by applicable law or agreed to in writing, software
11a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * See the License for the specific language governing permissions and
14a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * limitations under the License.
15a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase */
16a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
17a00f3865f55c5c9cb74510ee2b239d101230133cChet Haasepackage android.view;
18a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
19a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport android.animation.Animator;
20a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport android.animation.ValueAnimator;
21a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport android.animation.TimeInterpolator;
22a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
23a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport java.util.ArrayList;
24a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport java.util.HashMap;
25a00f3865f55c5c9cb74510ee2b239d101230133cChet Haaseimport java.util.Set;
26a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
27a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase/**
28a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * This class enables automatic and optimized animation of select properties on View objects.
29a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * If only one or two properties on a View object are being animated, then using an
30a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * {@link android.animation.ObjectAnimator} is fine; the property setters called by ObjectAnimator
31a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * are well equipped to do the right thing to set the property and invalidate the view
32a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * appropriately. But if several properties are animated simultaneously, or if you just want a
33a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * more convenient syntax to animate a specific property, then ViewPropertyAnimator might be
34a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * more well-suited to the task.
35a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
36d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase * <p>This class may provide better performance for several simultaneous animations, because
37d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase * it will optimize invalidate calls to take place only once for several properties instead of each
38d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase * animated property independently causing its own invalidation. Also, the syntax of using this
39a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * class could be easier to use because the caller need only tell the View object which
40d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase * property to animate, and the value to animate either to or by, and this class handles the
41a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * details of configuring the underlying Animator class and starting it.</p>
42a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
43a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * <p>This class is not constructed by the caller, but rather by the View whose properties
44a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * it will animate. Calls to {@link android.view.View#animate()} will return a reference
45a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase * to the appropriate ViewPropertyAnimator object for that View.</p>
46a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase *
47a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase */
48a00f3865f55c5c9cb74510ee2b239d101230133cChet Haasepublic class ViewPropertyAnimator {
49a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
50a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
51a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * The View whose properties are being animated by this class. This is set at
52a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * construction time.
53a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
54ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn    private final View mView;
55a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
56a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
57a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * The duration of the underlying Animator object. By default, we don't set the duration
58a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * on the Animator and just use its default duration. If the duration is ever set on this
59a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Animator, then we use the duration that it was set to.
60a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
61a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private long mDuration;
62a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
63a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
64a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * A flag indicating whether the duration has been set on this object. If not, we don't set
65a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * the duration on the underlying Animator, but instead just use its default duration.
66a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
67a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private boolean mDurationSet = false;
68a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
69a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
708d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * The startDelay of the underlying Animator object. By default, we don't set the startDelay
718d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * on the Animator and just use its default startDelay. If the startDelay is ever set on this
728d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Animator, then we use the startDelay that it was set to.
738d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
748d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    private long mStartDelay = 0;
758d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
768d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
778d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * A flag indicating whether the startDelay has been set on this object. If not, we don't set
788d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * the startDelay on the underlying Animator, but instead just use its default startDelay.
798d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
808d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    private boolean mStartDelaySet = false;
818d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
828d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
83a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * The interpolator of the underlying Animator object. By default, we don't set the interpolator
84a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * on the Animator and just use its default interpolator. If the interpolator is ever set on
85a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * this Animator, then we use the interpolator that it was set to.
86a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
87a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private TimeInterpolator mInterpolator;
88a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
89a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
90a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * A flag indicating whether the interpolator has been set on this object. If not, we don't set
91a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * the interpolator on the underlying Animator, but instead just use its default interpolator.
92a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
93a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private boolean mInterpolatorSet = false;
94a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
95a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
96a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Listener for the lifecycle events of the underlying
97a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
98a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private Animator.AnimatorListener mListener = null;
99a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
100a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
101a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This listener is the mechanism by which the underlying Animator causes changes to the
102a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * properties currently being animated, as well as the cleanup after an animation is
103a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * complete.
104a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
105a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private AnimatorEventListener mAnimatorEventListener = new AnimatorEventListener();
106a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
107a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
108a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This list holds the properties that have been asked to animate. We allow the caller to
109a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * request several animations prior to actually starting the underlying animator. This
110a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * enables us to run one single animator to handle several properties in parallel. Each
111a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * property is tossed onto the pending list until the animation actually starts (which is
112a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * done by posting it onto mView), at which time the pending list is cleared and the properties
113a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * on that list are added to the list of properties associated with that animator.
114a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
115a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    ArrayList<NameValuesHolder> mPendingAnimations = new ArrayList<NameValuesHolder>();
116c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private Runnable mPendingSetupAction;
117c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private Runnable mPendingCleanupAction;
118c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private Runnable mPendingOnStartAction;
119c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private Runnable mPendingOnEndAction;
120a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
121a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
122a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Constants used to associate a property being requested and the mechanism used to set
123d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * the property (this class calls directly into View to set the properties in question).
124a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
125a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int NONE           = 0x0000;
126a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int TRANSLATION_X  = 0x0001;
127a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int TRANSLATION_Y  = 0x0002;
128a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int SCALE_X        = 0x0004;
129a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int SCALE_Y        = 0x0008;
130a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int ROTATION       = 0x0010;
131a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int ROTATION_X     = 0x0020;
132a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int ROTATION_Y     = 0x0040;
133a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int X              = 0x0080;
134a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int Y              = 0x0100;
135a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int ALPHA          = 0x0200;
136a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
137a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static final int TRANSFORM_MASK = TRANSLATION_X | TRANSLATION_Y | SCALE_X | SCALE_Y |
138a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            ROTATION | ROTATION_X | ROTATION_Y | X | Y;
139a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
140a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
141a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * The mechanism by which the user can request several properties that are then animated
142a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * together works by posting this Runnable to start the underlying Animator. Every time
143a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * a property animation is requested, we cancel any previous postings of the Runnable
144a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * and re-post it. This means that we will only ever run the Runnable (and thus start the
145a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * underlying animator) after the caller is done setting the properties that should be
146a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * animated together.
147a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
148a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private Runnable mAnimationStarter = new Runnable() {
149a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
150a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void run() {
151a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            startAnimation();
152a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
153a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    };
154a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
155a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
156a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This class holds information about the overall animation being run on the set of
157a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * properties. The mask describes which properties are being animated and the
158a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * values holder is the list of all property/value objects.
159a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
160a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static class PropertyBundle {
161a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int mPropertyMask;
162a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        ArrayList<NameValuesHolder> mNameValuesHolder;
163ba592d200390d89723682f1a7e40d308d7804b36Chet Haase
164a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
165a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mPropertyMask = propertyMask;
166a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mNameValuesHolder = nameValuesHolder;
167a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
168ba592d200390d89723682f1a7e40d308d7804b36Chet Haase
169ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        /**
170ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * Removes the given property from being animated as a part of this
171ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * PropertyBundle. If the property was a part of this bundle, it returns
172ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * true to indicate that it was, in fact, canceled. This is an indication
173ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * to the caller that a cancellation actually occurred.
174ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         *
175ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * @param propertyConstant The property whose cancellation is requested.
176ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * @return true if the given property is a part of this bundle and if it
177ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         * has therefore been canceled.
178ba592d200390d89723682f1a7e40d308d7804b36Chet Haase         */
179ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        boolean cancel(int propertyConstant) {
180ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
181ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                int count = mNameValuesHolder.size();
182ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                for (int i = 0; i < count; ++i) {
183ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
184ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    if (nameValuesHolder.mNameConstant == propertyConstant) {
185ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        mNameValuesHolder.remove(i);
186ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        mPropertyMask &= ~propertyConstant;
187ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        return true;
188ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    }
189ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                }
190ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            }
191ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            return false;
192ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        }
193a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
194a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
195a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
196a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This list tracks the list of properties being animated by any particular animator.
197a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * In most situations, there would only ever be one animator running at a time. But it is
198a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * possible to request some properties to animate together, then while those properties
199a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * are animating, to request some other properties to animate together. The way that
200a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * works is by having this map associate the group of properties being animated with the
201a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * animator handling the animation. On every update event for an Animator, we ask the
202a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * map for the associated properties and set them accordingly.
203a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
204a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private HashMap<Animator, PropertyBundle> mAnimatorMap =
205a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            new HashMap<Animator, PropertyBundle>();
206c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private HashMap<Animator, Runnable> mAnimatorSetupMap;
207c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private HashMap<Animator, Runnable> mAnimatorCleanupMap;
208c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private HashMap<Animator, Runnable> mAnimatorOnStartMap;
209c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    private HashMap<Animator, Runnable> mAnimatorOnEndMap;
210a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
211a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
212a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This is the information we need to set each property during the animation.
213a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * mNameConstant is used to set the appropriate field in View, and the from/delta
214a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * values are used to calculate the animated value for a given animation fraction
215a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * during the animation.
216a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
217a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private static class NameValuesHolder {
218a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int mNameConstant;
219a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float mFromValue;
220a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float mDeltaValue;
221a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        NameValuesHolder(int nameConstant, float fromValue, float deltaValue) {
222a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mNameConstant = nameConstant;
223a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mFromValue = fromValue;
224a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mDeltaValue = deltaValue;
225a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
226a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
227a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
228a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
229a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Constructor, called by View. This is private by design, as the user should only
230a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * get a ViewPropertyAnimator by calling View.animate().
231a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
232a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param view The View associated with this ViewPropertyAnimator
233a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
234a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    ViewPropertyAnimator(View view) {
235a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mView = view;
236ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn        view.ensureTransformationInfo();
237a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
238a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
239a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
240a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Sets the duration for the underlying animator that animates the requested properties.
241a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * By default, the animator uses the default value for ValueAnimator. Calling this method
242a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * will cause the declared value to be used instead.
243a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param duration The length of ensuing property animations, in milliseconds. The value
244a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * cannot be negative.
245a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
246a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
247a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator setDuration(long duration) {
248a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        if (duration < 0) {
249a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            throw new IllegalArgumentException("Animators cannot have negative duration: " +
250a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    duration);
251a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
252a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mDurationSet = true;
253a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mDuration = duration;
254a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
255a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
256a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
257a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
2588d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Returns the current duration of property animations. If the duration was set on this
2598d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * object, that value is returned. Otherwise, the default value of the underlying Animator
2608d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * is returned.
2618d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     *
2628d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @see #setDuration(long)
2638d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @return The duration of animations, in milliseconds.
2648d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
2658d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public long getDuration() {
266cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase        if (mDurationSet) {
267cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase            return mDuration;
2688d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        } else {
2698d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            // Just return the default from ValueAnimator, since that's what we'd get if
2708d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            // the value has not been set otherwise
2718d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            return new ValueAnimator().getDuration();
2728d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        }
2738d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
2748d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
2758d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
2768d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Returns the current startDelay of property animations. If the startDelay was set on this
2778d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * object, that value is returned. Otherwise, the default value of the underlying Animator
2788d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * is returned.
2798d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     *
2808d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @see #setStartDelay(long)
2818d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @return The startDelay of animations, in milliseconds.
2828d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
2838d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public long getStartDelay() {
2848d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        if (mStartDelaySet) {
2858d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            return mStartDelay;
2868d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        } else {
2878d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            // Just return the default from ValueAnimator (0), since that's what we'd get if
2888d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            // the value has not been set otherwise
2898d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            return 0;
2908d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        }
2918d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
2928d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
2938d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
2948d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Sets the startDelay for the underlying animator that animates the requested properties.
2958d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * By default, the animator uses the default value for ValueAnimator. Calling this method
2968d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * will cause the declared value to be used instead.
2978d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @param startDelay The delay of ensuing property animations, in milliseconds. The value
2988d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * cannot be negative.
2998d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
3008d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
3018d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public ViewPropertyAnimator setStartDelay(long startDelay) {
3028d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        if (startDelay < 0) {
3038d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            throw new IllegalArgumentException("Animators cannot have negative duration: " +
3048d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                    startDelay);
3058d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        }
3068d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        mStartDelaySet = true;
3078d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        mStartDelay = startDelay;
3088d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        return this;
3098d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
3108d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
3118d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
312a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Sets the interpolator for the underlying animator that animates the requested properties.
313a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * By default, the animator uses the default interpolator for ValueAnimator. Calling this method
314a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * will cause the declared object to be used instead.
315a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
316a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param interpolator The TimeInterpolator to be used for ensuing property animations.
317a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
318a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
319a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
320a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mInterpolatorSet = true;
321a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mInterpolator = interpolator;
322a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
323a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
324a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
325a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
326a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Sets a listener for events in the underlying Animators that run the property
327a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * animations.
328a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
329a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param listener The listener to be called with AnimatorListener events.
330a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
331a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
332a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator setListener(Animator.AnimatorListener listener) {
333a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mListener = listener;
334a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
335a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
336a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
337a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
3388d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Starts the currently pending property animations immediately. Calling <code>start()</code>
3398d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * is optional because all animations start automatically at the next opportunity. However,
3408d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * if the animations are needed to start immediately and synchronously (not at the time when
3418d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * the next event is processed by the hierarchy, which is when the animations would begin
3428d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * otherwise), then this method can be used.
3438d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
3448d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public void start() {
3458d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        startAnimation();
3468d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
3478d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
3488d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
3498d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Cancels all property animations that are currently running or pending.
3508d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
3518d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public void cancel() {
3528d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        if (mAnimatorMap.size() > 0) {
3538d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            HashMap<Animator, PropertyBundle> mAnimatorMapCopy =
3548d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                    (HashMap<Animator, PropertyBundle>)mAnimatorMap.clone();
3558d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            Set<Animator> animatorSet = mAnimatorMapCopy.keySet();
3568d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            for (Animator runningAnim : animatorSet) {
3578d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                runningAnim.cancel();
3588d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            }
3598d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        }
3608d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        mPendingAnimations.clear();
3613a000a52d6863bd1c6c9822a9cfd83e00f3aaf79Chet Haase        mView.removeCallbacks(mAnimationStarter);
3628d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
3638d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
3648d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
365a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>x</code> property to be animated to the
366d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
367a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
368a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
369a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setX(float)
370a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
371a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
372a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator x(float value) {
373a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(X, value);
374a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
375a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
376a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
377a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
378a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>x</code> property to be animated by the
379d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
380a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
381a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
382a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setX(float)
383a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
384a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
385a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator xBy(float value) {
386a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(X, value);
387a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
388a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
389a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
390a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
391a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>y</code> property to be animated to the
392d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
393a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
394a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
395a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setY(float)
396a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
397a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
398a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator y(float value) {
399a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(Y, value);
400a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
401a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
402a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
403a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
404a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>y</code> property to be animated by the
405d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
406a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
407a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
408a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setY(float)
409a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
410a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
411a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator yBy(float value) {
412a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(Y, value);
413a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
414a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
415a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
416a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
417a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotation</code> property to be animated to the
418d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
419a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
420a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
421a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotation(float)
422a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
423a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
424a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotation(float value) {
425a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION, value);
426a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
427a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
428a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
429a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
430a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotation</code> property to be animated by the
431d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
432a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
433a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
434a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotation(float)
435a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
436a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
437a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationBy(float value) {
438a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION, value);
439a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
440a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
441a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
442a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
443a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated to the
444d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
445a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
446a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
447a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationX(float)
448a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
449a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
450a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationX(float value) {
451a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION_X, value);
452a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
453a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
454a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
455a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
456a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated by the
457d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
458a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
459a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
460a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationX(float)
461a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
462a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
463a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationXBy(float value) {
464a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION_X, value);
465a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
466a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
467a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
468a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
469a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated to the
470d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
471a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
472a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
473a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationY(float)
474a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
475a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
476a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationY(float value) {
477a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION_Y, value);
478a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
479a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
480a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
481a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
482a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated by the
483d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
484a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
485a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
486a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationY(float)
487a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
488a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
489a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationYBy(float value) {
490a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION_Y, value);
491a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
492a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
493a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
494a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
495a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationX</code> property to be animated to the
496d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
497a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
498a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
499a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationX(float)
500a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
501a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
502a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationX(float value) {
503a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(TRANSLATION_X, value);
504a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
505a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
506a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
507a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
508a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationX</code> property to be animated by the
509d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
510a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
511a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
512a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationX(float)
513a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
514a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
515a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationXBy(float value) {
516a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(TRANSLATION_X, value);
517a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
518a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
519a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
520a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
521a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationY</code> property to be animated to the
522d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
523a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
524a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
525a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationY(float)
526a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
527a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
528a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationY(float value) {
529a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(TRANSLATION_Y, value);
530a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
531a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
532a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
533a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
534a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationY</code> property to be animated by the
535d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
536a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
537a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
538a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationY(float)
539a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
540a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
541a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationYBy(float value) {
542a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(TRANSLATION_Y, value);
543a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
544a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
545a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
546a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
547a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated to the
548d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
549a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
550a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
551a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleX(float)
552a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
553a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
554a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleX(float value) {
555a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(SCALE_X, value);
556a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
557a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
558a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
559a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
560a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated by the
561d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
562a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
563a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
564a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleX(float)
565a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
566a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
567a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleXBy(float value) {
568a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(SCALE_X, value);
569a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
570a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
571a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
572a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
573a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated to the
574d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
575a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
576a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
577a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleY(float)
578a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
579a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
580a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleY(float value) {
581a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(SCALE_Y, value);
582a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
583a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
584a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
585a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
586a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated by the
587d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
588a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
589a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
590a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleY(float)
591a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
592a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
593a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleYBy(float value) {
594a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(SCALE_Y, value);
595a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
596a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
597a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
598a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
599a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>alpha</code> property to be animated to the
600d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
601a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
602a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
603a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setAlpha(float)
604a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
605a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
606a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator alpha(float value) {
607a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ALPHA, value);
608a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
609a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
610a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
611a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
612a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>alpha</code> property to be animated by the
613d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
614a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
615a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
616a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setAlpha(float)
617a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
618a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
619a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator alphaBy(float value) {
620a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ALPHA, value);
621a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
622a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
623a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
624a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
625c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * The View associated with this ViewPropertyAnimator will have its
626c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * {@link View#setLayerType(int, android.graphics.Paint) layer type} set to
627c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation. This state
628c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * is not persistent, either on the View or on this ViewPropertyAnimator: the layer type
629c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * of the View will be restored when the animation ends to what it was when this method was
630c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * called, and this setting on ViewPropertyAnimator is only valid for the next animation.
631c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * Note that calling this method and then independently setting the layer type of the View
632c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * (by a direct call to {@link View#setLayerType(int, android.graphics.Paint)}) will result
633c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * in some inconsistency, including having the layer type restored to its pre-withLayer()
634c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * value when the animation ends.
635c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
636c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @see View#setLayerType(int, android.graphics.Paint)
637c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
638c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
639c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withLayer() {
640c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase         mPendingSetupAction= new Runnable() {
641c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            @Override
642c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            public void run() {
643c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
644c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
645c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        };
646c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        final int currentLayerType = mView.getLayerType();
647c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingCleanupAction = new Runnable() {
648c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            @Override
649c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            public void run() {
650c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mView.setLayerType(currentLayerType, null);
651c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
652c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        };
653c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mAnimatorSetupMap == null) {
654c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorSetupMap = new HashMap<Animator, Runnable>();
655c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
656c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mAnimatorCleanupMap == null) {
657c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorCleanupMap = new HashMap<Animator, Runnable>();
658c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
659c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
660c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
661c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
662c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
663c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
664c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * Specifies an action to take place when the next animation runs. If there is a
665c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the
666c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * action will run after that startDelay expires, when the actual animation begins.
667c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate
668c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
669c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * in the application.
670c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
671c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @param runnable The action to run when the next animation starts.
672c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
673c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
674c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withStartAction(Runnable runnable) {
675c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingOnStartAction = runnable;
676c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (runnable != null && mAnimatorOnStartMap == null) {
677c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnStartMap = new HashMap<Animator, Runnable>();
678c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
679c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
680c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
681c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
682c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
683c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * Specifies an action to take place when the next animation ends. The action is only
684c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * run if the animation ends normally; if the ViewPropertyAnimator is canceled during
685c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * that animation, the runnable will not run.
686c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * This method, along with {@link #withStartAction(Runnable)}, is intended to help facilitate
687c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
688c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * in the application.
689c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
690c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * <p>For example, the following code animates a view to x=200 and then back to 0:</p>
691c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * <pre>
692c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     Runnable endAction = new Runnable() {
693c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *         public void run() {
694c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *             view.animate().x(0);
695c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *         }
696c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     };
697c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     view.animate().x(200).onEnd(endAction);
698c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * </pre>
699c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
700c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @param runnable The action to run when the next animation ends.
701c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
702c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
703c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withEndAction(Runnable runnable) {
704c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingOnEndAction = runnable;
705c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (runnable != null && mAnimatorOnEndMap == null) {
706c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnEndMap = new HashMap<Animator, Runnable>();
707c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
708c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
709c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
710c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
711c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
712a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Starts the underlying Animator for a set of properties. We use a single animator that
713a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * simply runs from 0 to 1, and then use that fractional value to set each property
714a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * value accordingly.
715a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
716a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void startAnimation() {
717a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
718a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        ArrayList<NameValuesHolder> nameValueList =
719a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                (ArrayList<NameValuesHolder>) mPendingAnimations.clone();
720a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mPendingAnimations.clear();
721a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int propertyMask = 0;
722a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int propertyCount = nameValueList.size();
723a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        for (int i = 0; i < propertyCount; ++i) {
724a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            NameValuesHolder nameValuesHolder = nameValueList.get(i);
725a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            propertyMask |= nameValuesHolder.mNameConstant;
726a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
727a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
728c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingSetupAction != null) {
729c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorSetupMap.put(animator, mPendingSetupAction);
730c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingSetupAction = null;
731c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
732c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingCleanupAction != null) {
733c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
734c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingCleanupAction = null;
735c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
736c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingOnStartAction != null) {
737c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
738c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingOnStartAction = null;
739c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
740c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingOnEndAction != null) {
741c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
742c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingOnEndAction = null;
743c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
744a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.addUpdateListener(mAnimatorEventListener);
745a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.addListener(mAnimatorEventListener);
746cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase        if (mStartDelaySet) {
747cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase            animator.setStartDelay(mStartDelay);
748cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase        }
749a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        if (mDurationSet) {
750a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            animator.setDuration(mDuration);
751a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
752a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        if (mInterpolatorSet) {
753a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            animator.setInterpolator(mInterpolator);
754a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
755a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.start();
756a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
757a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
758a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
759a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility function, called by the various x(), y(), etc. methods. This stores the
760d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * constant name for the property along with the from/delta values that will be used to
761a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * calculate and set the property during the animation. This structure is added to the
762a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * pending animations, awaiting the eventual start() of the underlying animator. A
763a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Runnable is posted to start the animation, and any pending such Runnable is canceled
764a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * (which enables us to end up starting just one animator for all of the properties
765a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * specified at one time).
766a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
767a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
768a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param toValue The value to which the property will animate
769a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
770a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void animateProperty(int constantName, float toValue) {
771a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float fromValue = getValue(constantName);
772a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float deltaValue = toValue - fromValue;
773a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(constantName, fromValue, deltaValue);
774a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
775a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
776a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
777a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility function, called by the various xBy(), yBy(), etc. methods. This method is
778a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * just like animateProperty(), except the value is an offset from the property's
779a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * current value, instead of an absolute "to" value.
780a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
781a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
782a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param byValue The amount by which the property will change
783a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
784a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void animatePropertyBy(int constantName, float byValue) {
785a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float fromValue = getValue(constantName);
786a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(constantName, fromValue, byValue);
787a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
788a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
789a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
790d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * Utility function, called by animateProperty() and animatePropertyBy(), which handles the
791a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * details of adding a pending animation and posting the request to start the animation.
792a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
793a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
794d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * @param startValue The starting value of the property
795a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param byValue The amount by which the property will change
796a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
797d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase    private void animatePropertyBy(int constantName, float startValue, float byValue) {
798ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        // First, cancel any existing animations on this property
799ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        if (mAnimatorMap.size() > 0) {
800ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            Animator animatorToCancel = null;
801ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            Set<Animator> animatorSet = mAnimatorMap.keySet();
802ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            for (Animator runningAnim : animatorSet) {
803ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                PropertyBundle bundle = mAnimatorMap.get(runningAnim);
804ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                if (bundle.cancel(constantName)) {
805ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // property was canceled - cancel the animation if it's now empty
806ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // Note that it's safe to break out here because every new animation
807ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // on a property will cancel a previous animation on that property, so
808ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // there can only ever be one such animation running.
809ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    if (bundle.mPropertyMask == NONE) {
8108d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                        // the animation is no longer changing anything - cancel it
811ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        animatorToCancel = runningAnim;
812ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        break;
813ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    }
814ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                }
815ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            }
816ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            if (animatorToCancel != null) {
817ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                animatorToCancel.cancel();
818ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            }
819ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        }
820ba592d200390d89723682f1a7e40d308d7804b36Chet Haase
821a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
822a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mPendingAnimations.add(nameValuePair);
8233a000a52d6863bd1c6c9822a9cfd83e00f3aaf79Chet Haase        mView.removeCallbacks(mAnimationStarter);
824a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mView.post(mAnimationStarter);
825a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
826a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
827a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
828a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method handles setting the property values directly in the View object's fields.
829a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * propertyConstant tells it which property should be set, value is the value to set
830a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * the property to.
831a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
832a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param propertyConstant The property to be set
833a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to set the property to
834a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
835a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void setValue(int propertyConstant, float value) {
836ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn        final View.TransformationInfo info = mView.mTransformationInfo;
837a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        switch (propertyConstant) {
838a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_X:
839ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationX = value;
840a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
841a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_Y:
842ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationY = value;
843a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
844a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION:
845ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotation = value;
846a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
847a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_X:
848ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotationX = value;
849a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
850a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_Y:
851ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotationY = value;
852a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
853a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_X:
854ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mScaleX = value;
855a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
856a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_Y:
857ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mScaleY = value;
858a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
859a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case X:
860ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationX = value - mView.mLeft;
861a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
862a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case Y:
863ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationY = value - mView.mTop;
864a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
865a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ALPHA:
866ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mAlpha = value;
867a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
868a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
869a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
870a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
871a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
872a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method gets the value of the named property from the View object.
873a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
874a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param propertyConstant The property whose value should be returned
875a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return float The value of the named property
876a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
877a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private float getValue(int propertyConstant) {
878ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn        final View.TransformationInfo info = mView.mTransformationInfo;
879a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        switch (propertyConstant) {
880a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_X:
881ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mTranslationX;
882a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_Y:
883ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mTranslationY;
884a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION:
885ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotation;
886a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_X:
887ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotationX;
888a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_Y:
889ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotationY;
890a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_X:
891ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mScaleX;
892a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_Y:
893ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mScaleY;
894a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case X:
895ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return mView.mLeft + info.mTranslationX;
896a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case Y:
897ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return mView.mTop + info.mTranslationY;
898a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ALPHA:
899ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mAlpha;
900a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
901a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return 0;
902a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
903a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
904a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
905a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility class that handles the various Animator events. The only ones we care
906a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * about are the end event (which we use to clean up the animator map when an animator
907a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * finishes) and the update event (which we use to calculate the current value of each
908a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * property and then set it on the view object).
909a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
910a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private class AnimatorEventListener
911a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
912a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
913a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationStart(Animator animation) {
914c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorSetupMap != null) {
915c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorSetupMap.get(animation);
916c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
917c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
918c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
919c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorSetupMap.remove(animation);
920c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
921c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnStartMap != null) {
922c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorOnStartMap.get(animation);
923c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
924c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
925c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
926c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnStartMap.remove(animation);
927c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
928a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
929a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationStart(animation);
930a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
931a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
932a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
933a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
934a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationCancel(Animator animation) {
935a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
936a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationCancel(animation);
937a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
938c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnEndMap != null) {
939c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnEndMap.remove(animation);
940c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
941a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
942a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
943a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
944a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationRepeat(Animator animation) {
945a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
946a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationRepeat(animation);
947a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
948a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
949a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
950a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
951a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationEnd(Animator animation) {
952a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
953a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationEnd(animation);
954a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
955c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnEndMap != null) {
956c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorOnEndMap.get(animation);
957c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
958c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
959c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
960c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnEndMap.remove(animation);
961c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
962c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorCleanupMap != null) {
963c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorCleanupMap.get(animation);
964c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
965c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
966c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
967c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorCleanupMap.remove(animation);
968c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
969a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mAnimatorMap.remove(animation);
970a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
971a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
972a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        /**
973a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * Calculate the current value for each property and set it on the view. Invalidate
974a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * the view object appropriately, depending on which properties are being animated.
975a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         *
976a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * @param animation The animator associated with the properties that need to be
977a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * set. This animator holds the animation fraction which we will use to calculate
978a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * the current value of each property.
979a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         */
980a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
981a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationUpdate(ValueAnimator animation) {
9820c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            PropertyBundle propertyBundle = mAnimatorMap.get(animation);
9830c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            if (propertyBundle == null) {
9840c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase                // Shouldn't happen, but just to play it safe
9850c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase                return;
9860c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            }
987a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // alpha requires slightly different treatment than the other (transform) properties.
988a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
989a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // logic is dependent on how the view handles an internal call to onSetAlpha().
990a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // We track what kinds of properties are set, and how alpha is handled when it is
991a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // set, and perform the invalidation steps appropriately.
992a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            boolean alphaHandled = false;
993a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mView.invalidateParentCaches();
994a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            float fraction = animation.getAnimatedFraction();
995a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            int propertyMask = propertyBundle.mPropertyMask;
996a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if ((propertyMask & TRANSFORM_MASK) != 0) {
997a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mView.invalidate(false);
998a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
999a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
1000a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (valueList != null) {
1001a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                int count = valueList.size();
1002a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                for (int i = 0; i < count; ++i) {
1003a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    NameValuesHolder values = valueList.get(i);
1004a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    float value = values.mFromValue + fraction * values.mDeltaValue;
1005a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    if (values.mNameConstant == ALPHA) {
1006a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                        alphaHandled = mView.setAlphaNoInvalidation(value);
1007a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    } else {
1008a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                        setValue(values.mNameConstant, value);
1009a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    }
1010a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                }
1011a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
1012a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if ((propertyMask & TRANSFORM_MASK) != 0) {
1013ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                mView.mTransformationInfo.mMatrixDirty = true;
1014a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mView.mPrivateFlags |= View.DRAWN; // force another invalidation
1015a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
1016a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // invalidate(false) in all cases except if alphaHandled gets set to true
1017a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // via the call to setAlphaNoInvalidation(), above
1018a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mView.invalidate(alphaHandled);
1019a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
1020a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
1021a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase}
1022