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() {
345500998d401e1c936bf60facecd5e9699d2eadb66Michael Jurka        mView.removeCallbacks(mAnimationStarter);
3468d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        startAnimation();
3478d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
3488d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
3498d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
3508d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     * Cancels all property animations that are currently running or pending.
3518d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase     */
3528d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    public void cancel() {
3538d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        if (mAnimatorMap.size() > 0) {
3548d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            HashMap<Animator, PropertyBundle> mAnimatorMapCopy =
3558d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                    (HashMap<Animator, PropertyBundle>)mAnimatorMap.clone();
3568d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            Set<Animator> animatorSet = mAnimatorMapCopy.keySet();
3578d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            for (Animator runningAnim : animatorSet) {
3588d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                runningAnim.cancel();
3598d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase            }
3608d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        }
3618d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase        mPendingAnimations.clear();
3623a000a52d6863bd1c6c9822a9cfd83e00f3aaf79Chet Haase        mView.removeCallbacks(mAnimationStarter);
3638d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    }
3648d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase
3658d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase    /**
366a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>x</code> property to be animated to the
367d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
368a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
369a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
370a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setX(float)
371a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
372a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
373a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator x(float value) {
374a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(X, value);
375a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
376a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
377a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
378a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
379a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>x</code> property to be animated by the
380d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
381a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
382a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
383a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setX(float)
384a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
385a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
386a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator xBy(float value) {
387a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(X, value);
388a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
389a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
390a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
391a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
392a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>y</code> property to be animated to the
393d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
394a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
395a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
396a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setY(float)
397a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
398a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
399a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator y(float value) {
400a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(Y, value);
401a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
402a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
403a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
404a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
405a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>y</code> property to be animated by the
406d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
407a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
408a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
409a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setY(float)
410a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
411a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
412a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator yBy(float value) {
413a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(Y, value);
414a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
415a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
416a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
417a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
418a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotation</code> property to be animated to the
419d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
420a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
421a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
422a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotation(float)
423a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
424a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
425a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotation(float value) {
426a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION, value);
427a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
428a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
429a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
430a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
431a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotation</code> property to be animated by the
432d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
433a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
434a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
435a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotation(float)
436a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
437a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
438a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationBy(float value) {
439a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION, value);
440a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
441a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
442a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
443a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
444a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated to the
445d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
446a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
447a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
448a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationX(float)
449a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
450a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
451a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationX(float value) {
452a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION_X, value);
453a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
454a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
455a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
456a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
457a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationX</code> property to be animated by the
458d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
459a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
460a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
461a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationX(float)
462a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
463a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
464a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationXBy(float value) {
465a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION_X, value);
466a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
467a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
468a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
469a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
470a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated to the
471d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
472a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
473a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
474a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationY(float)
475a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
476a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
477a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationY(float value) {
478a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ROTATION_Y, value);
479a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
480a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
481a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
482a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
483a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>rotationY</code> property to be animated by the
484d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
485a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
486a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
487a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setRotationY(float)
488a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
489a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
490a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator rotationYBy(float value) {
491a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ROTATION_Y, value);
492a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
493a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
494a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
495a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
496a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationX</code> property to be animated to the
497d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
498a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
499a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
500a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationX(float)
501a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
502a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
503a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationX(float value) {
504a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(TRANSLATION_X, value);
505a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
506a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
507a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
508a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
509a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationX</code> property to be animated by the
510d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
511a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
512a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
513a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationX(float)
514a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
515a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
516a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationXBy(float value) {
517a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(TRANSLATION_X, value);
518a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
519a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
520a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
521a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
522a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationY</code> property to be animated to the
523d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
524a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
525a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
526a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationY(float)
527a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
528a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
529a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationY(float value) {
530a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(TRANSLATION_Y, value);
531a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
532a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
533a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
534a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
535a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>translationY</code> property to be animated by the
536d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
537a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
538a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
539a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setTranslationY(float)
540a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
541a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
542a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator translationYBy(float value) {
543a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(TRANSLATION_Y, value);
544a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
545a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
546a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
547a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
548a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated to the
549d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
550a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
551a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
552a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleX(float)
553a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
554a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
555a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleX(float value) {
556a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(SCALE_X, value);
557a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
558a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
559a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
560a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
561a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleX</code> property to be animated by the
562d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
563a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
564a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
565a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleX(float)
566a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
567a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
568a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleXBy(float value) {
569a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(SCALE_X, value);
570a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
571a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
572a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
573a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
574a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated to the
575d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
576a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
577a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
578a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleY(float)
579a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
580a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
581a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleY(float value) {
582a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(SCALE_Y, value);
583a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
584a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
585a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
586a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
587a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>scaleY</code> property to be animated by the
588d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
589a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
590a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
591a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setScaleY(float)
592a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
593a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
594a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator scaleYBy(float value) {
595a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(SCALE_Y, value);
596a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
597a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
598a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
599a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
600a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>alpha</code> property to be animated to the
601d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
602a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
603a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to be animated to.
604a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setAlpha(float)
605a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
606a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
607a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator alpha(float value) {
608a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animateProperty(ALPHA, value);
609a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
610a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
611a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
612a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
613a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method will cause the View's <code>alpha</code> property to be animated by the
614d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * specified value. Animations already running on the property will be canceled.
615a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
616a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The amount to be animated by, as an offset from the current value.
617a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @see View#setAlpha(float)
618a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return This object, allowing calls to methods in this class to be chained.
619a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
620a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    public ViewPropertyAnimator alphaBy(float value) {
621a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(ALPHA, value);
622a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return this;
623a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
624a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
625a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
626c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * The View associated with this ViewPropertyAnimator will have its
627c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * {@link View#setLayerType(int, android.graphics.Paint) layer type} set to
628cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation.
629cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * As stated in the documentation for {@link View#LAYER_TYPE_HARDWARE},
630cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * the actual type of layer used internally depends on the runtime situation of the
631cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * view. If the activity and this view are hardware-accelerated, then the layer will be
632cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * accelerated as well. If the activity or the view is not accelerated, then the layer will
633cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * effectively be the same as {@link View#LAYER_TYPE_SOFTWARE}.
634cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     *
635cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * <p>This state is not persistent, either on the View or on this ViewPropertyAnimator: the
636cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * layer type of the View will be restored when the animation ends to what it was when this
637cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * method was called, and this setting on ViewPropertyAnimator is only valid for the next
638cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * animation. Note that calling this method and then independently setting the layer type of
639cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * the View (by a direct call to {@link View#setLayerType(int, android.graphics.Paint)}) will
640cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * result in some inconsistency, including having the layer type restored to its pre-withLayer()
641cb150fe9e6495256019b02be51e736679b57c1b5Chet Haase     * value when the animation ends.</p>
642c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
643c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @see View#setLayerType(int, android.graphics.Paint)
644c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
645c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
646c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withLayer() {
647c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase         mPendingSetupAction= new Runnable() {
648c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            @Override
649c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            public void run() {
650c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
651c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
652c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        };
653c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        final int currentLayerType = mView.getLayerType();
654c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingCleanupAction = new Runnable() {
655c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            @Override
656c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            public void run() {
657c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mView.setLayerType(currentLayerType, null);
658c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
659c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        };
660c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mAnimatorSetupMap == null) {
661c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorSetupMap = new HashMap<Animator, Runnable>();
662c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
663c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mAnimatorCleanupMap == null) {
664c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorCleanupMap = new HashMap<Animator, Runnable>();
665c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
666c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
667c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
668c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
669c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
670c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
671c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * Specifies an action to take place when the next animation runs. If there is a
672c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the
673c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * action will run after that startDelay expires, when the actual animation begins.
674c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate
675c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
676c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * in the application.
677c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
678c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @param runnable The action to run when the next animation starts.
679c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
680c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
681c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withStartAction(Runnable runnable) {
682c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingOnStartAction = runnable;
683c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (runnable != null && mAnimatorOnStartMap == null) {
684c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnStartMap = new HashMap<Animator, Runnable>();
685c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
686c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
687c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
688c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
689c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
690c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * Specifies an action to take place when the next animation ends. The action is only
691c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * run if the animation ends normally; if the ViewPropertyAnimator is canceled during
692c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * that animation, the runnable will not run.
693c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * This method, along with {@link #withStartAction(Runnable)}, is intended to help facilitate
694c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * choreographing ViewPropertyAnimator animations with other animations or actions
695c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * in the application.
696c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
697c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * <p>For example, the following code animates a view to x=200 and then back to 0:</p>
698c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * <pre>
699c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     Runnable endAction = new Runnable() {
700c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *         public void run() {
701c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *             view.animate().x(0);
702c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *         }
703c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     };
704c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *     view.animate().x(200).onEnd(endAction);
705c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * </pre>
706c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     *
707c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @param runnable The action to run when the next animation ends.
708c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     * @return This object, allowing calls to methods in this class to be chained.
709c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase     */
710c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    public ViewPropertyAnimator withEndAction(Runnable runnable) {
711c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        mPendingOnEndAction = runnable;
712c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (runnable != null && mAnimatorOnEndMap == null) {
713c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnEndMap = new HashMap<Animator, Runnable>();
714c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
715c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        return this;
716c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    }
717c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase
718c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase    /**
719a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Starts the underlying Animator for a set of properties. We use a single animator that
720a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * simply runs from 0 to 1, and then use that fractional value to set each property
721a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * value accordingly.
722a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
723a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void startAnimation() {
724563d4f2d461d264457b7e7068e2fc7b9b0bcafb3Chet Haase        mView.setHasTransientState(true);
725a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
726a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        ArrayList<NameValuesHolder> nameValueList =
727a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                (ArrayList<NameValuesHolder>) mPendingAnimations.clone();
728a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mPendingAnimations.clear();
729a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int propertyMask = 0;
730a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        int propertyCount = nameValueList.size();
731a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        for (int i = 0; i < propertyCount; ++i) {
732a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            NameValuesHolder nameValuesHolder = nameValueList.get(i);
733a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            propertyMask |= nameValuesHolder.mNameConstant;
734a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
735a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
736c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingSetupAction != null) {
737c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorSetupMap.put(animator, mPendingSetupAction);
738c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingSetupAction = null;
739c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
740c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingCleanupAction != null) {
741c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
742c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingCleanupAction = null;
743c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
744c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingOnStartAction != null) {
745c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
746c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingOnStartAction = null;
747c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
748c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        if (mPendingOnEndAction != null) {
749c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
750c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            mPendingOnEndAction = null;
751c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase        }
752a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.addUpdateListener(mAnimatorEventListener);
753a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.addListener(mAnimatorEventListener);
754cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase        if (mStartDelaySet) {
755cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase            animator.setStartDelay(mStartDelay);
756cbbd93ae701b9af2e5054d59286bdbf6275c2838Chet Haase        }
757a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        if (mDurationSet) {
758a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            animator.setDuration(mDuration);
759a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
760a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        if (mInterpolatorSet) {
761a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            animator.setInterpolator(mInterpolator);
762a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
763a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animator.start();
764a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
765a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
766a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
767a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility function, called by the various x(), y(), etc. methods. This stores the
768d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * constant name for the property along with the from/delta values that will be used to
769a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * calculate and set the property during the animation. This structure is added to the
770a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * pending animations, awaiting the eventual start() of the underlying animator. A
771a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Runnable is posted to start the animation, and any pending such Runnable is canceled
772a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * (which enables us to end up starting just one animator for all of the properties
773a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * specified at one time).
774a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
775a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
776a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param toValue The value to which the property will animate
777a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
778a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void animateProperty(int constantName, float toValue) {
779a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float fromValue = getValue(constantName);
780a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float deltaValue = toValue - fromValue;
781a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(constantName, fromValue, deltaValue);
782a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
783a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
784a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
785a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility function, called by the various xBy(), yBy(), etc. methods. This method is
786a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * just like animateProperty(), except the value is an offset from the property's
787a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * current value, instead of an absolute "to" value.
788a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
789a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
790a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param byValue The amount by which the property will change
791a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
792a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void animatePropertyBy(int constantName, float byValue) {
793a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        float fromValue = getValue(constantName);
794a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        animatePropertyBy(constantName, fromValue, byValue);
795a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
796a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
797a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
798d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * Utility function, called by animateProperty() and animatePropertyBy(), which handles the
799a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * details of adding a pending animation and posting the request to start the animation.
800a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
801a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param constantName The specifier for the property being animated
802d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase     * @param startValue The starting value of the property
803a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param byValue The amount by which the property will change
804a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
805d666cf320db4134938f72b0ffe18212997f8c8d8Chet Haase    private void animatePropertyBy(int constantName, float startValue, float byValue) {
806ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        // First, cancel any existing animations on this property
807ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        if (mAnimatorMap.size() > 0) {
808ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            Animator animatorToCancel = null;
809ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            Set<Animator> animatorSet = mAnimatorMap.keySet();
810ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            for (Animator runningAnim : animatorSet) {
811ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                PropertyBundle bundle = mAnimatorMap.get(runningAnim);
812ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                if (bundle.cancel(constantName)) {
813ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // property was canceled - cancel the animation if it's now empty
814ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // Note that it's safe to break out here because every new animation
815ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // on a property will cancel a previous animation on that property, so
816ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    // there can only ever be one such animation running.
817ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    if (bundle.mPropertyMask == NONE) {
8188d5f808f70c1d47437eaf49234c1b3a23c244040Chet Haase                        // the animation is no longer changing anything - cancel it
819ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        animatorToCancel = runningAnim;
820ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                        break;
821ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                    }
822ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                }
823ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            }
824ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            if (animatorToCancel != null) {
825ba592d200390d89723682f1a7e40d308d7804b36Chet Haase                animatorToCancel.cancel();
826ba592d200390d89723682f1a7e40d308d7804b36Chet Haase            }
827ba592d200390d89723682f1a7e40d308d7804b36Chet Haase        }
828ba592d200390d89723682f1a7e40d308d7804b36Chet Haase
829a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
830a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mPendingAnimations.add(nameValuePair);
8313a000a52d6863bd1c6c9822a9cfd83e00f3aaf79Chet Haase        mView.removeCallbacks(mAnimationStarter);
832a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        mView.post(mAnimationStarter);
833a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
834a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
835a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
836a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method handles setting the property values directly in the View object's fields.
837a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * propertyConstant tells it which property should be set, value is the value to set
838a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * the property to.
839a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
840a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param propertyConstant The property to be set
841a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param value The value to set the property to
842a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
843a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private void setValue(int propertyConstant, float value) {
844ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn        final View.TransformationInfo info = mView.mTransformationInfo;
8451271e2cc80b01d577e9db339459ef0222bb9320dChet Haase        final DisplayList displayList = mView.mDisplayList;
846a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        switch (propertyConstant) {
847a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_X:
848ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationX = value;
849db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setTranslationX(value);
850a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
851a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_Y:
852ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationY = value;
853db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setTranslationY(value);
854a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
855a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION:
856ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotation = value;
857db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setRotation(value);
858a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
859a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_X:
860ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotationX = value;
861db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setRotationX(value);
862a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
863a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_Y:
864ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mRotationY = value;
865db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setRotationY(value);
866a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
867a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_X:
868ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mScaleX = value;
869db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setScaleX(value);
870a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
871a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_Y:
872ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mScaleY = value;
873db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setScaleY(value);
874a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
875a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case X:
876ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationX = value - mView.mLeft;
877db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
878a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
879a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case Y:
880ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mTranslationY = value - mView.mTop;
881db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setTranslationY(value - mView.mTop);
882a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
883a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ALPHA:
884ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                info.mAlpha = value;
885db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase                if (displayList != null) displayList.setAlpha(value);
886a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                break;
887a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
888a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
889a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
890a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
891a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * This method gets the value of the named property from the View object.
892a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     *
893a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @param propertyConstant The property whose value should be returned
894a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * @return float The value of the named property
895a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
896a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private float getValue(int propertyConstant) {
897ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn        final View.TransformationInfo info = mView.mTransformationInfo;
898a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        switch (propertyConstant) {
899a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_X:
900ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mTranslationX;
901a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case TRANSLATION_Y:
902ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mTranslationY;
903a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION:
904ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotation;
905a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_X:
906ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotationX;
907a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ROTATION_Y:
908ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mRotationY;
909a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_X:
910ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mScaleX;
911a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case SCALE_Y:
912ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mScaleY;
913a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case X:
914ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return mView.mLeft + info.mTranslationX;
915a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case Y:
916ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return mView.mTop + info.mTranslationY;
917a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            case ALPHA:
918ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                return info.mAlpha;
919a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
920a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        return 0;
921a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
922a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
923a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    /**
924a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * Utility class that handles the various Animator events. The only ones we care
925a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * about are the end event (which we use to clean up the animator map when an animator
926a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * finishes) and the update event (which we use to calculate the current value of each
927a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     * property and then set it on the view object).
928a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase     */
929a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    private class AnimatorEventListener
930a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
931a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
932a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationStart(Animator animation) {
933c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorSetupMap != null) {
934c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorSetupMap.get(animation);
935c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
936c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
937c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
938c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorSetupMap.remove(animation);
939c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
940c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnStartMap != null) {
941c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorOnStartMap.get(animation);
942c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
943c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
944c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
945c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnStartMap.remove(animation);
946c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
947a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
948a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationStart(animation);
949a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
950a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
951a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
952a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
953a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationCancel(Animator animation) {
954a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
955a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationCancel(animation);
956a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
957c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnEndMap != null) {
958c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnEndMap.remove(animation);
959c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
960a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
961a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
962a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
963a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationRepeat(Animator animation) {
964a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
965a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationRepeat(animation);
966a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
967a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
968a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
969a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
970a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationEnd(Animator animation) {
971563d4f2d461d264457b7e7068e2fc7b9b0bcafb3Chet Haase            mView.setHasTransientState(false);
972a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (mListener != null) {
973a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                mListener.onAnimationEnd(animation);
974a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
975c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorOnEndMap != null) {
976c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorOnEndMap.get(animation);
977c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
978c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
979c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
980c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorOnEndMap.remove(animation);
981c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
982c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            if (mAnimatorCleanupMap != null) {
983c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                Runnable r = mAnimatorCleanupMap.get(animation);
984c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                if (r != null) {
985c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                    r.run();
986c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                }
987c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase                mAnimatorCleanupMap.remove(animation);
988c1ca665827f0c34419a55c005254c1aaa0d58b40Chet Haase            }
989a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            mAnimatorMap.remove(animation);
990a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
991a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase
992a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        /**
993a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * Calculate the current value for each property and set it on the view. Invalidate
994a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * the view object appropriately, depending on which properties are being animated.
995a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         *
996a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * @param animation The animator associated with the properties that need to be
997a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * set. This animator holds the animation fraction which we will use to calculate
998a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         * the current value of each property.
999a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase         */
1000a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        @Override
1001a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        public void onAnimationUpdate(ValueAnimator animation) {
10020c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            PropertyBundle propertyBundle = mAnimatorMap.get(animation);
10030c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            if (propertyBundle == null) {
10040c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase                // Shouldn't happen, but just to play it safe
10050c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase                return;
10060c6d83cc5625f967eb2e23cc7c232874cd9e60f9Chet Haase            }
10071271e2cc80b01d577e9db339459ef0222bb9320dChet Haase            boolean useDisplayListProperties = mView.mDisplayList != null;
10089d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase
1009a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // alpha requires slightly different treatment than the other (transform) properties.
1010a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
1011a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // logic is dependent on how the view handles an internal call to onSetAlpha().
1012a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // We track what kinds of properties are set, and how alpha is handled when it is
1013a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // set, and perform the invalidation steps appropriately.
1014a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            boolean alphaHandled = false;
10159d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase            if (!useDisplayListProperties) {
10169d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                mView.invalidateParentCaches();
10179d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase            }
1018a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            float fraction = animation.getAnimatedFraction();
1019a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            int propertyMask = propertyBundle.mPropertyMask;
1020a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if ((propertyMask & TRANSFORM_MASK) != 0) {
10219d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                mView.invalidateViewProperty(false, false);
1022a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
1023a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
1024a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if (valueList != null) {
1025a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                int count = valueList.size();
1026a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                for (int i = 0; i < count; ++i) {
1027a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    NameValuesHolder values = valueList.get(i);
1028a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    float value = values.mFromValue + fraction * values.mDeltaValue;
1029a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    if (values.mNameConstant == ALPHA) {
1030a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                        alphaHandled = mView.setAlphaNoInvalidation(value);
1031a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    } else {
1032a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                        setValue(values.mNameConstant, value);
1033a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                    }
1034a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase                }
1035a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
1036a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            if ((propertyMask & TRANSFORM_MASK) != 0) {
1037ddb715b238c098d8b561a44b9687f0bc67a4c141Dianne Hackborn                mView.mTransformationInfo.mMatrixDirty = true;
10389d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                if (!useDisplayListProperties) {
10394702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn                    mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
10409d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                }
1041a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            }
1042a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // invalidate(false) in all cases except if alphaHandled gets set to true
1043a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase            // via the call to setAlphaNoInvalidation(), above
10449d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase            if (alphaHandled) {
10459d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                mView.invalidate(true);
10469d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase            } else {
10479d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase                mView.invalidateViewProperty(false, false);
10489d1992deaeb3d60d5928f05b649a2cc654ba98a3Chet Haase            }
1049a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase        }
1050a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase    }
1051a00f3865f55c5c9cb74510ee2b239d101230133cChet Haase}
1052