blob: 9fa8f9c35d425b0b58c6bd4f43771c8ee257c96b [file] [log] [blame]
Chet Haasea00f3862011-02-22 06:34:40 -08001/*
Chet Haased666cf32011-03-01 07:31:30 -08002 * Copyright (C) 2011 The Android Open Source Project
Chet Haasea00f3862011-02-22 06:34:40 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.Animator;
Chet Haasea00f3862011-02-22 06:34:40 -080020import android.animation.TimeInterpolator;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070021import android.animation.ValueAnimator;
Mathew Inwoode5ad5982018-08-17 15:07:52 +010022import android.annotation.UnsupportedAppUsage;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070023
Chet Haasea00f3862011-02-22 06:34:40 -080024import java.util.ArrayList;
25import java.util.HashMap;
26import java.util.Set;
27
28/**
29 * This class enables automatic and optimized animation of select properties on View objects.
30 * If only one or two properties on a View object are being animated, then using an
31 * {@link android.animation.ObjectAnimator} is fine; the property setters called by ObjectAnimator
32 * are well equipped to do the right thing to set the property and invalidate the view
33 * appropriately. But if several properties are animated simultaneously, or if you just want a
34 * more convenient syntax to animate a specific property, then ViewPropertyAnimator might be
35 * more well-suited to the task.
36 *
Chet Haased666cf32011-03-01 07:31:30 -080037 * <p>This class may provide better performance for several simultaneous animations, because
38 * it will optimize invalidate calls to take place only once for several properties instead of each
39 * animated property independently causing its own invalidation. Also, the syntax of using this
Chet Haasea00f3862011-02-22 06:34:40 -080040 * class could be easier to use because the caller need only tell the View object which
Chet Haased666cf32011-03-01 07:31:30 -080041 * property to animate, and the value to animate either to or by, and this class handles the
Chet Haasea00f3862011-02-22 06:34:40 -080042 * details of configuring the underlying Animator class and starting it.</p>
43 *
44 * <p>This class is not constructed by the caller, but rather by the View whose properties
45 * it will animate. Calls to {@link android.view.View#animate()} will return a reference
46 * to the appropriate ViewPropertyAnimator object for that View.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070047 *
Chet Haasea00f3862011-02-22 06:34:40 -080048 */
49public class ViewPropertyAnimator {
50
51 /**
52 * The View whose properties are being animated by this class. This is set at
53 * construction time.
54 */
John Reck44244ff2014-06-20 14:44:58 -070055 final View mView;
Chet Haasea00f3862011-02-22 06:34:40 -080056
57 /**
58 * The duration of the underlying Animator object. By default, we don't set the duration
59 * on the Animator and just use its default duration. If the duration is ever set on this
60 * Animator, then we use the duration that it was set to.
61 */
62 private long mDuration;
63
64 /**
65 * A flag indicating whether the duration has been set on this object. If not, we don't set
66 * the duration on the underlying Animator, but instead just use its default duration.
67 */
68 private boolean mDurationSet = false;
69
70 /**
Chet Haase8d5f8082011-05-24 08:03:16 -070071 * The startDelay of the underlying Animator object. By default, we don't set the startDelay
72 * on the Animator and just use its default startDelay. If the startDelay is ever set on this
73 * Animator, then we use the startDelay that it was set to.
74 */
75 private long mStartDelay = 0;
76
77 /**
78 * A flag indicating whether the startDelay has been set on this object. If not, we don't set
79 * the startDelay on the underlying Animator, but instead just use its default startDelay.
80 */
81 private boolean mStartDelaySet = false;
82
83 /**
Chet Haasea00f3862011-02-22 06:34:40 -080084 * The interpolator of the underlying Animator object. By default, we don't set the interpolator
Vladislav Kaznacheev78f146f2015-06-15 06:58:59 +000085 * on the Animator and just use its default interpolator. If the interpolator is ever set on
86 * this Animator, then we use the interpolator that it was set to.
Chet Haasea00f3862011-02-22 06:34:40 -080087 */
88 private TimeInterpolator mInterpolator;
89
90 /**
Vladislav Kaznacheev78f146f2015-06-15 06:58:59 +000091 * A flag indicating whether the interpolator has been set on this object. If not, we don't set
92 * the interpolator on the underlying Animator, but instead just use its default interpolator.
93 */
94 private boolean mInterpolatorSet = false;
95
96 /**
Chet Haase87f4ae62013-09-06 18:29:56 -070097 * Listener for the lifecycle events of the underlying ValueAnimator object.
Chet Haasea00f3862011-02-22 06:34:40 -080098 */
99 private Animator.AnimatorListener mListener = null;
100
101 /**
Chet Haase87f4ae62013-09-06 18:29:56 -0700102 * Listener for the update events of the underlying ValueAnimator object.
103 */
104 private ValueAnimator.AnimatorUpdateListener mUpdateListener = null;
105
106 /**
Cyril Mottierd40acfb2013-07-25 10:08:29 +0200107 * A lazily-created ValueAnimator used in order to get some default animator properties
108 * (duration, start delay, interpolator, etc.).
109 */
110 private ValueAnimator mTempValueAnimator;
111
112 /**
John Reck918988c2014-05-19 10:28:35 -0700113 * A RenderThread-driven backend that may intercept startAnimation
114 */
Mathew Inwoode5ad5982018-08-17 15:07:52 +0100115 @UnsupportedAppUsage
John Reck918988c2014-05-19 10:28:35 -0700116 private ViewPropertyAnimatorRT mRTBackend;
117
118 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800119 * This listener is the mechanism by which the underlying Animator causes changes to the
120 * properties currently being animated, as well as the cleanup after an animation is
121 * complete.
122 */
123 private AnimatorEventListener mAnimatorEventListener = new AnimatorEventListener();
124
125 /**
126 * This list holds the properties that have been asked to animate. We allow the caller to
127 * request several animations prior to actually starting the underlying animator. This
128 * enables us to run one single animator to handle several properties in parallel. Each
129 * property is tossed onto the pending list until the animation actually starts (which is
130 * done by posting it onto mView), at which time the pending list is cleared and the properties
131 * on that list are added to the list of properties associated with that animator.
132 */
133 ArrayList<NameValuesHolder> mPendingAnimations = new ArrayList<NameValuesHolder>();
Chet Haasec1ca6652012-01-31 07:33:48 -0800134 private Runnable mPendingSetupAction;
135 private Runnable mPendingCleanupAction;
136 private Runnable mPendingOnStartAction;
137 private Runnable mPendingOnEndAction;
Chet Haasea00f3862011-02-22 06:34:40 -0800138
139 /**
140 * Constants used to associate a property being requested and the mechanism used to set
Chet Haased666cf32011-03-01 07:31:30 -0800141 * the property (this class calls directly into View to set the properties in question).
Chet Haasea00f3862011-02-22 06:34:40 -0800142 */
John Recke45b1fd2014-04-15 09:50:16 -0700143 static final int NONE = 0x0000;
144 static final int TRANSLATION_X = 0x0001;
145 static final int TRANSLATION_Y = 0x0002;
146 static final int TRANSLATION_Z = 0x0004;
147 static final int SCALE_X = 0x0008;
148 static final int SCALE_Y = 0x0010;
149 static final int ROTATION = 0x0020;
150 static final int ROTATION_X = 0x0040;
151 static final int ROTATION_Y = 0x0080;
152 static final int X = 0x0100;
153 static final int Y = 0x0200;
154 static final int Z = 0x0400;
155 static final int ALPHA = 0x0800;
Chet Haasea00f3862011-02-22 06:34:40 -0800156
Chris Craikf57776b2013-10-25 18:30:17 -0700157 private static final int TRANSFORM_MASK = TRANSLATION_X | TRANSLATION_Y | TRANSLATION_Z |
Chris Craikcc39e162014-04-25 18:34:11 -0700158 SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y | Z;
Chet Haasea00f3862011-02-22 06:34:40 -0800159
160 /**
161 * The mechanism by which the user can request several properties that are then animated
162 * together works by posting this Runnable to start the underlying Animator. Every time
163 * a property animation is requested, we cancel any previous postings of the Runnable
164 * and re-post it. This means that we will only ever run the Runnable (and thus start the
165 * underlying animator) after the caller is done setting the properties that should be
166 * animated together.
167 */
168 private Runnable mAnimationStarter = new Runnable() {
169 @Override
170 public void run() {
171 startAnimation();
172 }
173 };
174
175 /**
176 * This class holds information about the overall animation being run on the set of
177 * properties. The mask describes which properties are being animated and the
178 * values holder is the list of all property/value objects.
179 */
180 private static class PropertyBundle {
181 int mPropertyMask;
182 ArrayList<NameValuesHolder> mNameValuesHolder;
Chet Haaseba592d202011-02-25 11:35:17 -0800183
Chet Haasea00f3862011-02-22 06:34:40 -0800184 PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
185 mPropertyMask = propertyMask;
186 mNameValuesHolder = nameValuesHolder;
187 }
Chet Haaseba592d202011-02-25 11:35:17 -0800188
189 /**
190 * Removes the given property from being animated as a part of this
191 * PropertyBundle. If the property was a part of this bundle, it returns
192 * true to indicate that it was, in fact, canceled. This is an indication
193 * to the caller that a cancellation actually occurred.
194 *
195 * @param propertyConstant The property whose cancellation is requested.
196 * @return true if the given property is a part of this bundle and if it
197 * has therefore been canceled.
198 */
199 boolean cancel(int propertyConstant) {
200 if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
201 int count = mNameValuesHolder.size();
202 for (int i = 0; i < count; ++i) {
203 NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
204 if (nameValuesHolder.mNameConstant == propertyConstant) {
205 mNameValuesHolder.remove(i);
206 mPropertyMask &= ~propertyConstant;
207 return true;
208 }
209 }
210 }
211 return false;
212 }
Chet Haasea00f3862011-02-22 06:34:40 -0800213 }
214
215 /**
216 * This list tracks the list of properties being animated by any particular animator.
217 * In most situations, there would only ever be one animator running at a time. But it is
218 * possible to request some properties to animate together, then while those properties
219 * are animating, to request some other properties to animate together. The way that
220 * works is by having this map associate the group of properties being animated with the
221 * animator handling the animation. On every update event for an Animator, we ask the
222 * map for the associated properties and set them accordingly.
223 */
224 private HashMap<Animator, PropertyBundle> mAnimatorMap =
225 new HashMap<Animator, PropertyBundle>();
Chet Haasec1ca6652012-01-31 07:33:48 -0800226 private HashMap<Animator, Runnable> mAnimatorSetupMap;
227 private HashMap<Animator, Runnable> mAnimatorCleanupMap;
228 private HashMap<Animator, Runnable> mAnimatorOnStartMap;
229 private HashMap<Animator, Runnable> mAnimatorOnEndMap;
Chet Haasea00f3862011-02-22 06:34:40 -0800230
231 /**
232 * This is the information we need to set each property during the animation.
233 * mNameConstant is used to set the appropriate field in View, and the from/delta
234 * values are used to calculate the animated value for a given animation fraction
235 * during the animation.
236 */
John Reck918988c2014-05-19 10:28:35 -0700237 static class NameValuesHolder {
Chet Haasea00f3862011-02-22 06:34:40 -0800238 int mNameConstant;
239 float mFromValue;
240 float mDeltaValue;
241 NameValuesHolder(int nameConstant, float fromValue, float deltaValue) {
242 mNameConstant = nameConstant;
243 mFromValue = fromValue;
244 mDeltaValue = deltaValue;
245 }
246 }
247
248 /**
249 * Constructor, called by View. This is private by design, as the user should only
250 * get a ViewPropertyAnimator by calling View.animate().
251 *
252 * @param view The View associated with this ViewPropertyAnimator
253 */
254 ViewPropertyAnimator(View view) {
255 mView = view;
Dianne Hackbornddb715b2011-09-09 14:43:39 -0700256 view.ensureTransformationInfo();
Chet Haasea00f3862011-02-22 06:34:40 -0800257 }
258
259 /**
260 * Sets the duration for the underlying animator that animates the requested properties.
261 * By default, the animator uses the default value for ValueAnimator. Calling this method
262 * will cause the declared value to be used instead.
263 * @param duration The length of ensuing property animations, in milliseconds. The value
264 * cannot be negative.
265 * @return This object, allowing calls to methods in this class to be chained.
266 */
267 public ViewPropertyAnimator setDuration(long duration) {
268 if (duration < 0) {
269 throw new IllegalArgumentException("Animators cannot have negative duration: " +
270 duration);
271 }
272 mDurationSet = true;
273 mDuration = duration;
274 return this;
275 }
276
277 /**
Chet Haase8d5f8082011-05-24 08:03:16 -0700278 * Returns the current duration of property animations. If the duration was set on this
279 * object, that value is returned. Otherwise, the default value of the underlying Animator
280 * is returned.
281 *
282 * @see #setDuration(long)
283 * @return The duration of animations, in milliseconds.
284 */
285 public long getDuration() {
Chet Haasecbbd93a2011-08-08 17:34:25 -0700286 if (mDurationSet) {
287 return mDuration;
Chet Haase8d5f8082011-05-24 08:03:16 -0700288 } else {
289 // Just return the default from ValueAnimator, since that's what we'd get if
290 // the value has not been set otherwise
Cyril Mottierd40acfb2013-07-25 10:08:29 +0200291 if (mTempValueAnimator == null) {
292 mTempValueAnimator = new ValueAnimator();
293 }
294 return mTempValueAnimator.getDuration();
Chet Haase8d5f8082011-05-24 08:03:16 -0700295 }
296 }
297
298 /**
299 * Returns the current startDelay of property animations. If the startDelay was set on this
300 * object, that value is returned. Otherwise, the default value of the underlying Animator
301 * is returned.
302 *
303 * @see #setStartDelay(long)
304 * @return The startDelay of animations, in milliseconds.
305 */
306 public long getStartDelay() {
307 if (mStartDelaySet) {
308 return mStartDelay;
309 } else {
310 // Just return the default from ValueAnimator (0), since that's what we'd get if
311 // the value has not been set otherwise
312 return 0;
313 }
314 }
315
316 /**
317 * Sets the startDelay for the underlying animator that animates the requested properties.
318 * By default, the animator uses the default value for ValueAnimator. Calling this method
319 * will cause the declared value to be used instead.
320 * @param startDelay The delay of ensuing property animations, in milliseconds. The value
321 * cannot be negative.
322 * @return This object, allowing calls to methods in this class to be chained.
323 */
324 public ViewPropertyAnimator setStartDelay(long startDelay) {
325 if (startDelay < 0) {
Cyril Mottier772bafa2013-10-02 16:57:57 +0200326 throw new IllegalArgumentException("Animators cannot have negative start " +
327 "delay: " + startDelay);
Chet Haase8d5f8082011-05-24 08:03:16 -0700328 }
329 mStartDelaySet = true;
330 mStartDelay = startDelay;
331 return this;
332 }
333
334 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800335 * Sets the interpolator for the underlying animator that animates the requested properties.
336 * By default, the animator uses the default interpolator for ValueAnimator. Calling this method
337 * will cause the declared object to be used instead.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700338 *
John Recka0b13bd2014-07-01 08:34:47 -0700339 * @param interpolator The TimeInterpolator to be used for ensuing property animations. A value
340 * of <code>null</code> will result in linear interpolation.
Chet Haasea00f3862011-02-22 06:34:40 -0800341 * @return This object, allowing calls to methods in this class to be chained.
342 */
343 public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
Vladislav Kaznacheev78f146f2015-06-15 06:58:59 +0000344 mInterpolatorSet = true;
Chet Haasea00f3862011-02-22 06:34:40 -0800345 mInterpolator = interpolator;
346 return this;
347 }
348
349 /**
Chet Haase430742f2013-04-12 11:18:36 -0700350 * Returns the timing interpolator that this animation uses.
351 *
352 * @return The timing interpolator for this animation.
353 */
354 public TimeInterpolator getInterpolator() {
Vladislav Kaznacheev78f146f2015-06-15 06:58:59 +0000355 if (mInterpolatorSet) {
Cyril Mottierd40acfb2013-07-25 10:08:29 +0200356 return mInterpolator;
357 } else {
358 // Just return the default from ValueAnimator, since that's what we'd get if
359 // the value has not been set otherwise
360 if (mTempValueAnimator == null) {
361 mTempValueAnimator = new ValueAnimator();
362 }
363 return mTempValueAnimator.getInterpolator();
364 }
Chet Haase430742f2013-04-12 11:18:36 -0700365 }
366
367 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800368 * Sets a listener for events in the underlying Animators that run the property
369 * animations.
370 *
Chet Haase87f4ae62013-09-06 18:29:56 -0700371 * @see Animator.AnimatorListener
372 *
373 * @param listener The listener to be called with AnimatorListener events. A value of
374 * <code>null</code> removes any existing listener.
Chet Haasea00f3862011-02-22 06:34:40 -0800375 * @return This object, allowing calls to methods in this class to be chained.
376 */
377 public ViewPropertyAnimator setListener(Animator.AnimatorListener listener) {
378 mListener = listener;
379 return this;
380 }
381
John Reck918988c2014-05-19 10:28:35 -0700382 Animator.AnimatorListener getListener() {
383 return mListener;
384 }
385
Chet Haasea00f3862011-02-22 06:34:40 -0800386 /**
Chet Haase87f4ae62013-09-06 18:29:56 -0700387 * Sets a listener for update events in the underlying ValueAnimator that runs
388 * the property animations. Note that the underlying animator is animating between
389 * 0 and 1 (these values are then turned into the actual property values internally
390 * by ViewPropertyAnimator). So the animator cannot give information on the current
391 * values of the properties being animated by this ViewPropertyAnimator, although
392 * the view object itself can be queried to get the current values.
393 *
394 * @see android.animation.ValueAnimator.AnimatorUpdateListener
395 *
396 * @param listener The listener to be called with update events. A value of
397 * <code>null</code> removes any existing listener.
398 * @return This object, allowing calls to methods in this class to be chained.
399 */
400 public ViewPropertyAnimator setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
401 mUpdateListener = listener;
402 return this;
403 }
404
John Reck918988c2014-05-19 10:28:35 -0700405 ValueAnimator.AnimatorUpdateListener getUpdateListener() {
406 return mUpdateListener;
407 }
408
Chet Haase87f4ae62013-09-06 18:29:56 -0700409 /**
Chet Haase8d5f8082011-05-24 08:03:16 -0700410 * Starts the currently pending property animations immediately. Calling <code>start()</code>
411 * is optional because all animations start automatically at the next opportunity. However,
412 * if the animations are needed to start immediately and synchronously (not at the time when
413 * the next event is processed by the hierarchy, which is when the animations would begin
414 * otherwise), then this method can be used.
415 */
416 public void start() {
Michael Jurka500998d2012-05-13 15:35:02 -0700417 mView.removeCallbacks(mAnimationStarter);
Chet Haase8d5f8082011-05-24 08:03:16 -0700418 startAnimation();
419 }
420
421 /**
422 * Cancels all property animations that are currently running or pending.
423 */
424 public void cancel() {
425 if (mAnimatorMap.size() > 0) {
426 HashMap<Animator, PropertyBundle> mAnimatorMapCopy =
427 (HashMap<Animator, PropertyBundle>)mAnimatorMap.clone();
428 Set<Animator> animatorSet = mAnimatorMapCopy.keySet();
429 for (Animator runningAnim : animatorSet) {
430 runningAnim.cancel();
431 }
432 }
433 mPendingAnimations.clear();
Chet Haase5637b7d2014-08-28 07:53:59 -0700434 mPendingSetupAction = null;
435 mPendingCleanupAction = null;
436 mPendingOnStartAction = null;
437 mPendingOnEndAction = null;
Chet Haase3a000a52011-06-16 13:55:11 -0700438 mView.removeCallbacks(mAnimationStarter);
John Reck22184722014-06-20 07:19:30 -0700439 if (mRTBackend != null) {
440 mRTBackend.cancelAll();
441 }
Chet Haase8d5f8082011-05-24 08:03:16 -0700442 }
443
444 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800445 * This method will cause the View's <code>x</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800446 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800447 *
448 * @param value The value to be animated to.
449 * @see View#setX(float)
450 * @return This object, allowing calls to methods in this class to be chained.
451 */
452 public ViewPropertyAnimator x(float value) {
453 animateProperty(X, value);
454 return this;
455 }
456
457 /**
458 * This method will cause the View's <code>x</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800459 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800460 *
461 * @param value The amount to be animated by, as an offset from the current value.
462 * @see View#setX(float)
463 * @return This object, allowing calls to methods in this class to be chained.
464 */
465 public ViewPropertyAnimator xBy(float value) {
466 animatePropertyBy(X, value);
467 return this;
468 }
469
470 /**
471 * This method will cause the View's <code>y</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800472 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800473 *
474 * @param value The value to be animated to.
475 * @see View#setY(float)
476 * @return This object, allowing calls to methods in this class to be chained.
477 */
478 public ViewPropertyAnimator y(float value) {
479 animateProperty(Y, value);
480 return this;
481 }
482
483 /**
484 * This method will cause the View's <code>y</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800485 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800486 *
487 * @param value The amount to be animated by, as an offset from the current value.
488 * @see View#setY(float)
489 * @return This object, allowing calls to methods in this class to be chained.
490 */
491 public ViewPropertyAnimator yBy(float value) {
492 animatePropertyBy(Y, value);
493 return this;
494 }
495
496 /**
Chris Craikcc39e162014-04-25 18:34:11 -0700497 * This method will cause the View's <code>z</code> property to be animated to the
498 * specified value. Animations already running on the property will be canceled.
499 *
500 * @param value The value to be animated to.
501 * @see View#setZ(float)
502 * @return This object, allowing calls to methods in this class to be chained.
503 */
504 public ViewPropertyAnimator z(float value) {
505 animateProperty(Z, value);
506 return this;
507 }
508
509 /**
510 * This method will cause the View's <code>z</code> property to be animated by the
511 * specified value. Animations already running on the property will be canceled.
512 *
513 * @param value The amount to be animated by, as an offset from the current value.
514 * @see View#setZ(float)
515 * @return This object, allowing calls to methods in this class to be chained.
516 */
517 public ViewPropertyAnimator zBy(float value) {
518 animatePropertyBy(Z, value);
519 return this;
520 }
521
522 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800523 * This method will cause the View's <code>rotation</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800524 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800525 *
526 * @param value The value to be animated to.
527 * @see View#setRotation(float)
528 * @return This object, allowing calls to methods in this class to be chained.
529 */
530 public ViewPropertyAnimator rotation(float value) {
531 animateProperty(ROTATION, value);
532 return this;
533 }
534
535 /**
536 * This method will cause the View's <code>rotation</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800537 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800538 *
539 * @param value The amount to be animated by, as an offset from the current value.
540 * @see View#setRotation(float)
541 * @return This object, allowing calls to methods in this class to be chained.
542 */
543 public ViewPropertyAnimator rotationBy(float value) {
544 animatePropertyBy(ROTATION, value);
545 return this;
546 }
547
548 /**
549 * This method will cause the View's <code>rotationX</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800550 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800551 *
552 * @param value The value to be animated to.
553 * @see View#setRotationX(float)
554 * @return This object, allowing calls to methods in this class to be chained.
555 */
556 public ViewPropertyAnimator rotationX(float value) {
557 animateProperty(ROTATION_X, value);
558 return this;
559 }
560
561 /**
562 * This method will cause the View's <code>rotationX</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800563 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800564 *
565 * @param value The amount to be animated by, as an offset from the current value.
566 * @see View#setRotationX(float)
567 * @return This object, allowing calls to methods in this class to be chained.
568 */
569 public ViewPropertyAnimator rotationXBy(float value) {
570 animatePropertyBy(ROTATION_X, value);
571 return this;
572 }
573
574 /**
575 * This method will cause the View's <code>rotationY</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800576 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800577 *
578 * @param value The value to be animated to.
579 * @see View#setRotationY(float)
580 * @return This object, allowing calls to methods in this class to be chained.
581 */
582 public ViewPropertyAnimator rotationY(float value) {
583 animateProperty(ROTATION_Y, value);
584 return this;
585 }
586
587 /**
588 * This method will cause the View's <code>rotationY</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800589 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800590 *
591 * @param value The amount to be animated by, as an offset from the current value.
592 * @see View#setRotationY(float)
593 * @return This object, allowing calls to methods in this class to be chained.
594 */
595 public ViewPropertyAnimator rotationYBy(float value) {
596 animatePropertyBy(ROTATION_Y, value);
597 return this;
598 }
599
600 /**
601 * This method will cause the View's <code>translationX</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800602 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800603 *
604 * @param value The value to be animated to.
605 * @see View#setTranslationX(float)
606 * @return This object, allowing calls to methods in this class to be chained.
607 */
608 public ViewPropertyAnimator translationX(float value) {
609 animateProperty(TRANSLATION_X, value);
610 return this;
611 }
612
613 /**
614 * This method will cause the View's <code>translationX</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800615 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800616 *
617 * @param value The amount to be animated by, as an offset from the current value.
618 * @see View#setTranslationX(float)
619 * @return This object, allowing calls to methods in this class to be chained.
620 */
621 public ViewPropertyAnimator translationXBy(float value) {
622 animatePropertyBy(TRANSLATION_X, value);
623 return this;
624 }
625
626 /**
627 * This method will cause the View's <code>translationY</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800628 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800629 *
630 * @param value The value to be animated to.
631 * @see View#setTranslationY(float)
632 * @return This object, allowing calls to methods in this class to be chained.
633 */
634 public ViewPropertyAnimator translationY(float value) {
635 animateProperty(TRANSLATION_Y, value);
636 return this;
637 }
638
639 /**
640 * This method will cause the View's <code>translationY</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800641 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800642 *
643 * @param value The amount to be animated by, as an offset from the current value.
644 * @see View#setTranslationY(float)
645 * @return This object, allowing calls to methods in this class to be chained.
646 */
647 public ViewPropertyAnimator translationYBy(float value) {
648 animatePropertyBy(TRANSLATION_Y, value);
649 return this;
650 }
651
652 /**
Chris Craikd863a102013-12-19 13:31:15 -0800653 * This method will cause the View's <code>translationZ</code> property to be animated to the
654 * specified value. Animations already running on the property will be canceled.
655 *
656 * @param value The value to be animated to.
657 * @see View#setTranslationZ(float)
658 * @return This object, allowing calls to methods in this class to be chained.
659 */
660 public ViewPropertyAnimator translationZ(float value) {
661 animateProperty(TRANSLATION_Z, value);
662 return this;
663 }
664
665 /**
666 * This method will cause the View's <code>translationZ</code> property to be animated by the
667 * specified value. Animations already running on the property will be canceled.
668 *
669 * @param value The amount to be animated by, as an offset from the current value.
670 * @see View#setTranslationZ(float)
671 * @return This object, allowing calls to methods in this class to be chained.
672 */
673 public ViewPropertyAnimator translationZBy(float value) {
674 animatePropertyBy(TRANSLATION_Z, value);
675 return this;
676 }
677 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800678 * This method will cause the View's <code>scaleX</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800679 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800680 *
681 * @param value The value to be animated to.
682 * @see View#setScaleX(float)
683 * @return This object, allowing calls to methods in this class to be chained.
684 */
685 public ViewPropertyAnimator scaleX(float value) {
686 animateProperty(SCALE_X, value);
687 return this;
688 }
689
690 /**
691 * This method will cause the View's <code>scaleX</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800692 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800693 *
694 * @param value The amount to be animated by, as an offset from the current value.
695 * @see View#setScaleX(float)
696 * @return This object, allowing calls to methods in this class to be chained.
697 */
698 public ViewPropertyAnimator scaleXBy(float value) {
699 animatePropertyBy(SCALE_X, value);
700 return this;
701 }
702
703 /**
704 * This method will cause the View's <code>scaleY</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800705 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800706 *
707 * @param value The value to be animated to.
708 * @see View#setScaleY(float)
709 * @return This object, allowing calls to methods in this class to be chained.
710 */
711 public ViewPropertyAnimator scaleY(float value) {
712 animateProperty(SCALE_Y, value);
713 return this;
714 }
715
716 /**
717 * This method will cause the View's <code>scaleY</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800718 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800719 *
720 * @param value The amount to be animated by, as an offset from the current value.
721 * @see View#setScaleY(float)
722 * @return This object, allowing calls to methods in this class to be chained.
723 */
724 public ViewPropertyAnimator scaleYBy(float value) {
725 animatePropertyBy(SCALE_Y, value);
726 return this;
727 }
728
729 /**
730 * This method will cause the View's <code>alpha</code> property to be animated to the
Chet Haased666cf32011-03-01 07:31:30 -0800731 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800732 *
733 * @param value The value to be animated to.
734 * @see View#setAlpha(float)
735 * @return This object, allowing calls to methods in this class to be chained.
736 */
737 public ViewPropertyAnimator alpha(float value) {
738 animateProperty(ALPHA, value);
739 return this;
740 }
741
742 /**
743 * This method will cause the View's <code>alpha</code> property to be animated by the
Chet Haased666cf32011-03-01 07:31:30 -0800744 * specified value. Animations already running on the property will be canceled.
Chet Haasea00f3862011-02-22 06:34:40 -0800745 *
746 * @param value The amount to be animated by, as an offset from the current value.
747 * @see View#setAlpha(float)
748 * @return This object, allowing calls to methods in this class to be chained.
749 */
750 public ViewPropertyAnimator alphaBy(float value) {
751 animatePropertyBy(ALPHA, value);
752 return this;
753 }
754
755 /**
Chet Haasec1ca6652012-01-31 07:33:48 -0800756 * The View associated with this ViewPropertyAnimator will have its
757 * {@link View#setLayerType(int, android.graphics.Paint) layer type} set to
Chet Haasecb150fe2012-05-03 15:15:05 -0700758 * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation.
759 * As stated in the documentation for {@link View#LAYER_TYPE_HARDWARE},
760 * the actual type of layer used internally depends on the runtime situation of the
761 * view. If the activity and this view are hardware-accelerated, then the layer will be
762 * accelerated as well. If the activity or the view is not accelerated, then the layer will
763 * effectively be the same as {@link View#LAYER_TYPE_SOFTWARE}.
764 *
765 * <p>This state is not persistent, either on the View or on this ViewPropertyAnimator: the
766 * layer type of the View will be restored when the animation ends to what it was when this
767 * method was called, and this setting on ViewPropertyAnimator is only valid for the next
768 * animation. Note that calling this method and then independently setting the layer type of
769 * the View (by a direct call to {@link View#setLayerType(int, android.graphics.Paint)}) will
770 * result in some inconsistency, including having the layer type restored to its pre-withLayer()
771 * value when the animation ends.</p>
Chet Haasec1ca6652012-01-31 07:33:48 -0800772 *
773 * @see View#setLayerType(int, android.graphics.Paint)
774 * @return This object, allowing calls to methods in this class to be chained.
775 */
776 public ViewPropertyAnimator withLayer() {
777 mPendingSetupAction= new Runnable() {
778 @Override
779 public void run() {
780 mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
Chet Haase5fd37232013-09-13 19:01:52 -0700781 if (mView.isAttachedToWindow()) {
782 mView.buildLayer();
783 }
Chet Haasec1ca6652012-01-31 07:33:48 -0800784 }
785 };
786 final int currentLayerType = mView.getLayerType();
787 mPendingCleanupAction = new Runnable() {
788 @Override
789 public void run() {
790 mView.setLayerType(currentLayerType, null);
791 }
792 };
793 if (mAnimatorSetupMap == null) {
794 mAnimatorSetupMap = new HashMap<Animator, Runnable>();
795 }
796 if (mAnimatorCleanupMap == null) {
797 mAnimatorCleanupMap = new HashMap<Animator, Runnable>();
798 }
799
800 return this;
801 }
802
803 /**
804 * Specifies an action to take place when the next animation runs. If there is a
805 * {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the
806 * action will run after that startDelay expires, when the actual animation begins.
807 * This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate
808 * choreographing ViewPropertyAnimator animations with other animations or actions
809 * in the application.
810 *
811 * @param runnable The action to run when the next animation starts.
812 * @return This object, allowing calls to methods in this class to be chained.
813 */
814 public ViewPropertyAnimator withStartAction(Runnable runnable) {
815 mPendingOnStartAction = runnable;
816 if (runnable != null && mAnimatorOnStartMap == null) {
817 mAnimatorOnStartMap = new HashMap<Animator, Runnable>();
818 }
819 return this;
820 }
821
822 /**
823 * Specifies an action to take place when the next animation ends. The action is only
824 * run if the animation ends normally; if the ViewPropertyAnimator is canceled during
825 * that animation, the runnable will not run.
826 * This method, along with {@link #withStartAction(Runnable)}, is intended to help facilitate
827 * choreographing ViewPropertyAnimator animations with other animations or actions
828 * in the application.
829 *
830 * <p>For example, the following code animates a view to x=200 and then back to 0:</p>
831 * <pre>
832 * Runnable endAction = new Runnable() {
833 * public void run() {
834 * view.animate().x(0);
835 * }
836 * };
Robert Ly8ee2a702012-12-17 15:00:08 -0800837 * view.animate().x(200).withEndAction(endAction);
Chet Haasec1ca6652012-01-31 07:33:48 -0800838 * </pre>
839 *
840 * @param runnable The action to run when the next animation ends.
841 * @return This object, allowing calls to methods in this class to be chained.
842 */
843 public ViewPropertyAnimator withEndAction(Runnable runnable) {
844 mPendingOnEndAction = runnable;
845 if (runnable != null && mAnimatorOnEndMap == null) {
846 mAnimatorOnEndMap = new HashMap<Animator, Runnable>();
847 }
848 return this;
849 }
850
John Reck918988c2014-05-19 10:28:35 -0700851 boolean hasActions() {
852 return mPendingSetupAction != null
853 || mPendingCleanupAction != null
854 || mPendingOnStartAction != null
855 || mPendingOnEndAction != null;
856 }
857
Chet Haasec1ca6652012-01-31 07:33:48 -0800858 /**
Chet Haasea00f3862011-02-22 06:34:40 -0800859 * Starts the underlying Animator for a set of properties. We use a single animator that
860 * simply runs from 0 to 1, and then use that fractional value to set each property
861 * value accordingly.
862 */
863 private void startAnimation() {
John Reck918988c2014-05-19 10:28:35 -0700864 if (mRTBackend != null && mRTBackend.startAnimation(this)) {
865 return;
866 }
Chet Haase563d4f22012-04-18 16:20:08 -0700867 mView.setHasTransientState(true);
Chet Haasea00f3862011-02-22 06:34:40 -0800868 ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
869 ArrayList<NameValuesHolder> nameValueList =
870 (ArrayList<NameValuesHolder>) mPendingAnimations.clone();
871 mPendingAnimations.clear();
872 int propertyMask = 0;
873 int propertyCount = nameValueList.size();
874 for (int i = 0; i < propertyCount; ++i) {
875 NameValuesHolder nameValuesHolder = nameValueList.get(i);
876 propertyMask |= nameValuesHolder.mNameConstant;
877 }
Chet Haasea00f3862011-02-22 06:34:40 -0800878 mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
Chet Haasec1ca6652012-01-31 07:33:48 -0800879 if (mPendingSetupAction != null) {
880 mAnimatorSetupMap.put(animator, mPendingSetupAction);
881 mPendingSetupAction = null;
882 }
883 if (mPendingCleanupAction != null) {
884 mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
885 mPendingCleanupAction = null;
886 }
887 if (mPendingOnStartAction != null) {
888 mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
889 mPendingOnStartAction = null;
890 }
891 if (mPendingOnEndAction != null) {
892 mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
893 mPendingOnEndAction = null;
894 }
Chet Haasea00f3862011-02-22 06:34:40 -0800895 animator.addUpdateListener(mAnimatorEventListener);
896 animator.addListener(mAnimatorEventListener);
Chet Haasecbbd93a2011-08-08 17:34:25 -0700897 if (mStartDelaySet) {
898 animator.setStartDelay(mStartDelay);
899 }
Chet Haasea00f3862011-02-22 06:34:40 -0800900 if (mDurationSet) {
901 animator.setDuration(mDuration);
902 }
Vladislav Kaznacheev78f146f2015-06-15 06:58:59 +0000903 if (mInterpolatorSet) {
Chet Haasea00f3862011-02-22 06:34:40 -0800904 animator.setInterpolator(mInterpolator);
905 }
906 animator.start();
907 }
908
909 /**
910 * Utility function, called by the various x(), y(), etc. methods. This stores the
Chet Haased666cf32011-03-01 07:31:30 -0800911 * constant name for the property along with the from/delta values that will be used to
Chet Haasea00f3862011-02-22 06:34:40 -0800912 * calculate and set the property during the animation. This structure is added to the
913 * pending animations, awaiting the eventual start() of the underlying animator. A
914 * Runnable is posted to start the animation, and any pending such Runnable is canceled
915 * (which enables us to end up starting just one animator for all of the properties
916 * specified at one time).
917 *
918 * @param constantName The specifier for the property being animated
919 * @param toValue The value to which the property will animate
920 */
921 private void animateProperty(int constantName, float toValue) {
922 float fromValue = getValue(constantName);
923 float deltaValue = toValue - fromValue;
924 animatePropertyBy(constantName, fromValue, deltaValue);
925 }
926
927 /**
928 * Utility function, called by the various xBy(), yBy(), etc. methods. This method is
929 * just like animateProperty(), except the value is an offset from the property's
930 * current value, instead of an absolute "to" value.
931 *
932 * @param constantName The specifier for the property being animated
933 * @param byValue The amount by which the property will change
934 */
935 private void animatePropertyBy(int constantName, float byValue) {
936 float fromValue = getValue(constantName);
937 animatePropertyBy(constantName, fromValue, byValue);
938 }
939
940 /**
Chet Haased666cf32011-03-01 07:31:30 -0800941 * Utility function, called by animateProperty() and animatePropertyBy(), which handles the
Chet Haasea00f3862011-02-22 06:34:40 -0800942 * details of adding a pending animation and posting the request to start the animation.
943 *
944 * @param constantName The specifier for the property being animated
Chet Haased666cf32011-03-01 07:31:30 -0800945 * @param startValue The starting value of the property
Chet Haasea00f3862011-02-22 06:34:40 -0800946 * @param byValue The amount by which the property will change
947 */
Chet Haased666cf32011-03-01 07:31:30 -0800948 private void animatePropertyBy(int constantName, float startValue, float byValue) {
Chet Haaseba592d202011-02-25 11:35:17 -0800949 // First, cancel any existing animations on this property
950 if (mAnimatorMap.size() > 0) {
951 Animator animatorToCancel = null;
952 Set<Animator> animatorSet = mAnimatorMap.keySet();
953 for (Animator runningAnim : animatorSet) {
954 PropertyBundle bundle = mAnimatorMap.get(runningAnim);
955 if (bundle.cancel(constantName)) {
956 // property was canceled - cancel the animation if it's now empty
957 // Note that it's safe to break out here because every new animation
958 // on a property will cancel a previous animation on that property, so
959 // there can only ever be one such animation running.
960 if (bundle.mPropertyMask == NONE) {
Chet Haase8d5f8082011-05-24 08:03:16 -0700961 // the animation is no longer changing anything - cancel it
Chet Haaseba592d202011-02-25 11:35:17 -0800962 animatorToCancel = runningAnim;
963 break;
964 }
965 }
966 }
967 if (animatorToCancel != null) {
968 animatorToCancel.cancel();
969 }
970 }
971
Chet Haasea00f3862011-02-22 06:34:40 -0800972 NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
973 mPendingAnimations.add(nameValuePair);
Chet Haase3a000a52011-06-16 13:55:11 -0700974 mView.removeCallbacks(mAnimationStarter);
Chet Haasedcfbd6a2013-05-09 14:40:21 -0700975 mView.postOnAnimation(mAnimationStarter);
Chet Haasea00f3862011-02-22 06:34:40 -0800976 }
977
978 /**
979 * This method handles setting the property values directly in the View object's fields.
980 * propertyConstant tells it which property should be set, value is the value to set
981 * the property to.
982 *
983 * @param propertyConstant The property to be set
984 * @param value The value to set the property to
985 */
986 private void setValue(int propertyConstant, float value) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -0700987 final View.TransformationInfo info = mView.mTransformationInfo;
Chris Craik64a12e12014-03-28 18:12:12 -0700988 final RenderNode renderNode = mView.mRenderNode;
Chet Haasea00f3862011-02-22 06:34:40 -0800989 switch (propertyConstant) {
990 case TRANSLATION_X:
Chris Craik49e6c732014-03-31 12:34:11 -0700991 renderNode.setTranslationX(value);
Chet Haasea00f3862011-02-22 06:34:40 -0800992 break;
993 case TRANSLATION_Y:
Chris Craik49e6c732014-03-31 12:34:11 -0700994 renderNode.setTranslationY(value);
Chet Haasea00f3862011-02-22 06:34:40 -0800995 break;
Chris Craikf57776b2013-10-25 18:30:17 -0700996 case TRANSLATION_Z:
Chris Craik49e6c732014-03-31 12:34:11 -0700997 renderNode.setTranslationZ(value);
Chris Craikf57776b2013-10-25 18:30:17 -0700998 break;
Chet Haasea00f3862011-02-22 06:34:40 -0800999 case ROTATION:
Chris Craik49e6c732014-03-31 12:34:11 -07001000 renderNode.setRotation(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001001 break;
1002 case ROTATION_X:
Chris Craik49e6c732014-03-31 12:34:11 -07001003 renderNode.setRotationX(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001004 break;
1005 case ROTATION_Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001006 renderNode.setRotationY(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001007 break;
1008 case SCALE_X:
Chris Craik49e6c732014-03-31 12:34:11 -07001009 renderNode.setScaleX(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001010 break;
1011 case SCALE_Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001012 renderNode.setScaleY(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001013 break;
1014 case X:
Chris Craik49e6c732014-03-31 12:34:11 -07001015 renderNode.setTranslationX(value - mView.mLeft);
Chet Haasea00f3862011-02-22 06:34:40 -08001016 break;
1017 case Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001018 renderNode.setTranslationY(value - mView.mTop);
Chet Haasea00f3862011-02-22 06:34:40 -08001019 break;
Chris Craikcc39e162014-04-25 18:34:11 -07001020 case Z:
1021 renderNode.setTranslationZ(value - renderNode.getElevation());
1022 break;
Chet Haasea00f3862011-02-22 06:34:40 -08001023 case ALPHA:
Dianne Hackbornddb715b2011-09-09 14:43:39 -07001024 info.mAlpha = value;
Chris Craik49e6c732014-03-31 12:34:11 -07001025 renderNode.setAlpha(value);
Chet Haasea00f3862011-02-22 06:34:40 -08001026 break;
1027 }
1028 }
1029
1030 /**
1031 * This method gets the value of the named property from the View object.
1032 *
1033 * @param propertyConstant The property whose value should be returned
1034 * @return float The value of the named property
1035 */
1036 private float getValue(int propertyConstant) {
Chris Craik49e6c732014-03-31 12:34:11 -07001037 final RenderNode node = mView.mRenderNode;
Chet Haasea00f3862011-02-22 06:34:40 -08001038 switch (propertyConstant) {
1039 case TRANSLATION_X:
Chris Craik49e6c732014-03-31 12:34:11 -07001040 return node.getTranslationX();
Chet Haasea00f3862011-02-22 06:34:40 -08001041 case TRANSLATION_Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001042 return node.getTranslationY();
Chris Craikf57776b2013-10-25 18:30:17 -07001043 case TRANSLATION_Z:
Chris Craik49e6c732014-03-31 12:34:11 -07001044 return node.getTranslationZ();
Chet Haasea00f3862011-02-22 06:34:40 -08001045 case ROTATION:
Chris Craik49e6c732014-03-31 12:34:11 -07001046 return node.getRotation();
Chet Haasea00f3862011-02-22 06:34:40 -08001047 case ROTATION_X:
Chris Craik49e6c732014-03-31 12:34:11 -07001048 return node.getRotationX();
Chet Haasea00f3862011-02-22 06:34:40 -08001049 case ROTATION_Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001050 return node.getRotationY();
Chet Haasea00f3862011-02-22 06:34:40 -08001051 case SCALE_X:
Chris Craik49e6c732014-03-31 12:34:11 -07001052 return node.getScaleX();
Chet Haasea00f3862011-02-22 06:34:40 -08001053 case SCALE_Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001054 return node.getScaleY();
Chet Haasea00f3862011-02-22 06:34:40 -08001055 case X:
Chris Craik49e6c732014-03-31 12:34:11 -07001056 return mView.mLeft + node.getTranslationX();
Chet Haasea00f3862011-02-22 06:34:40 -08001057 case Y:
Chris Craik49e6c732014-03-31 12:34:11 -07001058 return mView.mTop + node.getTranslationY();
Chris Craikcc39e162014-04-25 18:34:11 -07001059 case Z:
1060 return node.getElevation() + node.getTranslationZ();
Chet Haasea00f3862011-02-22 06:34:40 -08001061 case ALPHA:
Chris Craik49e6c732014-03-31 12:34:11 -07001062 return mView.mTransformationInfo.mAlpha;
Chet Haasea00f3862011-02-22 06:34:40 -08001063 }
1064 return 0;
1065 }
1066
1067 /**
1068 * Utility class that handles the various Animator events. The only ones we care
1069 * about are the end event (which we use to clean up the animator map when an animator
1070 * finishes) and the update event (which we use to calculate the current value of each
1071 * property and then set it on the view object).
1072 */
1073 private class AnimatorEventListener
1074 implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
1075 @Override
1076 public void onAnimationStart(Animator animation) {
Chet Haasec1ca6652012-01-31 07:33:48 -08001077 if (mAnimatorSetupMap != null) {
1078 Runnable r = mAnimatorSetupMap.get(animation);
1079 if (r != null) {
1080 r.run();
1081 }
1082 mAnimatorSetupMap.remove(animation);
1083 }
1084 if (mAnimatorOnStartMap != null) {
1085 Runnable r = mAnimatorOnStartMap.get(animation);
1086 if (r != null) {
1087 r.run();
1088 }
1089 mAnimatorOnStartMap.remove(animation);
1090 }
Chet Haasea00f3862011-02-22 06:34:40 -08001091 if (mListener != null) {
1092 mListener.onAnimationStart(animation);
1093 }
1094 }
1095
1096 @Override
1097 public void onAnimationCancel(Animator animation) {
1098 if (mListener != null) {
1099 mListener.onAnimationCancel(animation);
1100 }
Chet Haasec1ca6652012-01-31 07:33:48 -08001101 if (mAnimatorOnEndMap != null) {
1102 mAnimatorOnEndMap.remove(animation);
1103 }
Chet Haasea00f3862011-02-22 06:34:40 -08001104 }
1105
1106 @Override
1107 public void onAnimationRepeat(Animator animation) {
1108 if (mListener != null) {
1109 mListener.onAnimationRepeat(animation);
1110 }
1111 }
1112
1113 @Override
1114 public void onAnimationEnd(Animator animation) {
Chet Haase563d4f22012-04-18 16:20:08 -07001115 mView.setHasTransientState(false);
George Mountf643fb02016-03-31 15:45:35 +00001116 if (mAnimatorCleanupMap != null) {
1117 Runnable r = mAnimatorCleanupMap.get(animation);
1118 if (r != null) {
1119 r.run();
1120 }
1121 mAnimatorCleanupMap.remove(animation);
1122 }
Chet Haasea00f3862011-02-22 06:34:40 -08001123 if (mListener != null) {
1124 mListener.onAnimationEnd(animation);
1125 }
George Mounte9a4f872016-03-29 07:39:02 -07001126 if (mAnimatorOnEndMap != null) {
1127 Runnable r = mAnimatorOnEndMap.get(animation);
1128 if (r != null) {
1129 r.run();
1130 }
1131 mAnimatorOnEndMap.remove(animation);
1132 }
Chet Haasea00f3862011-02-22 06:34:40 -08001133 mAnimatorMap.remove(animation);
1134 }
1135
1136 /**
1137 * Calculate the current value for each property and set it on the view. Invalidate
1138 * the view object appropriately, depending on which properties are being animated.
1139 *
1140 * @param animation The animator associated with the properties that need to be
1141 * set. This animator holds the animation fraction which we will use to calculate
1142 * the current value of each property.
1143 */
1144 @Override
1145 public void onAnimationUpdate(ValueAnimator animation) {
Chet Haase0c6d83cc2011-12-01 08:38:13 -08001146 PropertyBundle propertyBundle = mAnimatorMap.get(animation);
1147 if (propertyBundle == null) {
1148 // Shouldn't happen, but just to play it safe
1149 return;
1150 }
Chris Craik30485452014-05-27 19:18:10 -07001151
1152 boolean hardwareAccelerated = mView.isHardwareAccelerated();
Chet Haase9d1992d2012-03-13 11:03:25 -07001153
Chet Haasea00f3862011-02-22 06:34:40 -08001154 // alpha requires slightly different treatment than the other (transform) properties.
1155 // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
1156 // logic is dependent on how the view handles an internal call to onSetAlpha().
1157 // We track what kinds of properties are set, and how alpha is handled when it is
1158 // set, and perform the invalidation steps appropriately.
1159 boolean alphaHandled = false;
Chris Craik30485452014-05-27 19:18:10 -07001160 if (!hardwareAccelerated) {
Chet Haase9d1992d2012-03-13 11:03:25 -07001161 mView.invalidateParentCaches();
1162 }
Chet Haasea00f3862011-02-22 06:34:40 -08001163 float fraction = animation.getAnimatedFraction();
Chet Haasea00f3862011-02-22 06:34:40 -08001164 int propertyMask = propertyBundle.mPropertyMask;
1165 if ((propertyMask & TRANSFORM_MASK) != 0) {
Chris Craik30485452014-05-27 19:18:10 -07001166 mView.invalidateViewProperty(hardwareAccelerated, false);
Chet Haasea00f3862011-02-22 06:34:40 -08001167 }
1168 ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
1169 if (valueList != null) {
1170 int count = valueList.size();
1171 for (int i = 0; i < count; ++i) {
1172 NameValuesHolder values = valueList.get(i);
1173 float value = values.mFromValue + fraction * values.mDeltaValue;
1174 if (values.mNameConstant == ALPHA) {
1175 alphaHandled = mView.setAlphaNoInvalidation(value);
1176 } else {
1177 setValue(values.mNameConstant, value);
1178 }
1179 }
1180 }
1181 if ((propertyMask & TRANSFORM_MASK) != 0) {
Chris Craik30485452014-05-27 19:18:10 -07001182 if (!hardwareAccelerated) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07001183 mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
Chet Haase9d1992d2012-03-13 11:03:25 -07001184 }
Chet Haasea00f3862011-02-22 06:34:40 -08001185 }
1186 // invalidate(false) in all cases except if alphaHandled gets set to true
1187 // via the call to setAlphaNoInvalidation(), above
Chet Haase9d1992d2012-03-13 11:03:25 -07001188 if (alphaHandled) {
1189 mView.invalidate(true);
1190 } else {
1191 mView.invalidateViewProperty(false, false);
1192 }
Chet Haase87f4ae62013-09-06 18:29:56 -07001193 if (mUpdateListener != null) {
1194 mUpdateListener.onAnimationUpdate(animation);
1195 }
Chet Haasea00f3862011-02-22 06:34:40 -08001196 }
1197 }
1198}