blob: 3b60aee8f6043fa6ebc2f27d8785be621af90176 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view.animation;
18
Tor Norbyee8760542015-06-19 10:47:25 -070019import android.annotation.AnimRes;
Tor Norbye80756e32015-03-02 09:39:27 -080020import android.annotation.ColorInt;
Tor Norbye417ee5b2015-03-10 20:57:37 -070021import android.annotation.InterpolatorRes;
Mathew Inwoodfb75be92018-07-27 14:34:22 +010022import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.Context;
24import android.content.res.TypedArray;
Brian Carlstrom877e0b92010-11-19 14:04:05 -080025import android.graphics.RectF;
Jelle Fresenb89473d2019-02-08 10:12:24 +000026import android.os.Build;
Romain Guy393a52c2012-05-22 20:21:08 -070027import android.os.Handler;
Brian Carlstrom877e0b92010-11-19 14:04:05 -080028import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.util.AttributeSet;
30import android.util.TypedValue;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070031
Brian Carlstrom877e0b92010-11-19 14:04:05 -080032import dalvik.system.CloseGuard;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34/**
35 * Abstraction for an Animation that can be applied to Views, Surfaces, or
36 * other objects. See the {@link android.view.animation animation package
37 * description file}.
38 */
39public abstract class Animation implements Cloneable {
40 /**
41 * Repeat the animation indefinitely.
42 */
43 public static final int INFINITE = -1;
44
45 /**
46 * When the animation reaches the end and the repeat count is INFINTE_REPEAT
47 * or a positive value, the animation restarts from the beginning.
48 */
49 public static final int RESTART = 1;
50
51 /**
52 * When the animation reaches the end and the repeat count is INFINTE_REPEAT
53 * or a positive value, the animation plays backward (and then forward again).
54 */
55 public static final int REVERSE = 2;
56
57 /**
58 * Can be used as the start time to indicate the start time should be the current
59 * time when {@link #getTransformation(long, Transformation)} is invoked for the
60 * first animation frame. This can is useful for short animations.
61 */
62 public static final int START_ON_FIRST_FRAME = -1;
63
64 /**
65 * The specified dimension is an absolute number of pixels.
66 */
67 public static final int ABSOLUTE = 0;
68
69 /**
70 * The specified dimension holds a float and should be multiplied by the
71 * height or width of the object being animated.
72 */
73 public static final int RELATIVE_TO_SELF = 1;
74
75 /**
76 * The specified dimension holds a float and should be multiplied by the
77 * height or width of the parent of the object being animated.
78 */
79 public static final int RELATIVE_TO_PARENT = 2;
80
81 /**
82 * Requests that the content being animated be kept in its current Z
83 * order.
84 */
85 public static final int ZORDER_NORMAL = 0;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 /**
88 * Requests that the content being animated be forced on top of all other
89 * content for the duration of the animation.
90 */
91 public static final int ZORDER_TOP = 1;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 /**
94 * Requests that the content being animated be forced under all other
95 * content for the duration of the animation.
96 */
97 public static final int ZORDER_BOTTOM = -1;
Brian Carlstrom877e0b92010-11-19 14:04:05 -080098
Andreas Gampe56c560a2016-04-06 13:03:02 -070099 // Use a preload holder to isolate static initialization into inner class, which allows
100 // Animation and its subclasses to be compile-time initialized.
101 private static class NoImagePreloadHolder {
102 public static final boolean USE_CLOSEGUARD
103 = SystemProperties.getBoolean("log.closeguard.Animation", false);
104 }
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 /**
107 * Set by {@link #getTransformation(long, Transformation)} when the animation ends.
108 */
109 boolean mEnded = false;
110
111 /**
112 * Set by {@link #getTransformation(long, Transformation)} when the animation starts.
113 */
114 boolean mStarted = false;
115
116 /**
117 * Set by {@link #getTransformation(long, Transformation)} when the animation repeats
118 * in REVERSE mode.
119 */
120 boolean mCycleFlip = false;
121
122 /**
123 * This value must be set to true by {@link #initialize(int, int, int, int)}. It
124 * indicates the animation was successfully initialized and can be played.
125 */
126 boolean mInitialized = false;
127
128 /**
129 * Indicates whether the animation transformation should be applied before the
Chet Haased8991c42011-08-24 07:20:53 -0700130 * animation starts. The value of this variable is only relevant if mFillEnabled is true;
131 * otherwise it is assumed to be true.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 */
133 boolean mFillBefore = true;
134
135 /**
136 * Indicates whether the animation transformation should be applied after the
137 * animation ends.
138 */
139 boolean mFillAfter = false;
140
141 /**
Chet Haased8991c42011-08-24 07:20:53 -0700142 * Indicates whether fillBefore should be taken into account.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 */
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700144 boolean mFillEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
146 /**
147 * The time in milliseconds at which the animation must start;
148 */
149 long mStartTime = -1;
150
151 /**
152 * The delay in milliseconds after which the animation must start. When the
153 * start offset is > 0, the start time of the animation is startTime + startOffset.
154 */
155 long mStartOffset;
156
157 /**
158 * The duration of one animation cycle in milliseconds.
159 */
160 long mDuration;
161
162 /**
163 * The number of times the animation must repeat. By default, an animation repeats
164 * indefinitely.
165 */
166 int mRepeatCount = 0;
167
168 /**
169 * Indicates how many times the animation was repeated.
170 */
171 int mRepeated = 0;
172
173 /**
174 * The behavior of the animation when it repeats. The repeat mode is either
175 * {@link #RESTART} or {@link #REVERSE}.
176 *
177 */
178 int mRepeatMode = RESTART;
179
180 /**
181 * The interpolator used by the animation to smooth the movement.
182 */
183 Interpolator mInterpolator;
184
185 /**
Jelle Fresen65d21712018-11-30 10:23:25 +0000186 * An animation listener to be notified when the animation starts, ends or repeats.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 */
Jelle Fresenb89473d2019-02-08 10:12:24 +0000188 // If you need to chain the AnimationListener, wrap the existing Animation into an AnimationSet
189 // and add your new listener to that set
190 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117519981)
Jelle Fresen65d21712018-11-30 10:23:25 +0000191 private AnimationListener mListener;
192
193 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * Desired Z order mode during animation.
195 */
196 private int mZAdjustment;
Chet Haase48460322010-06-11 14:22:25 -0700197
198 /**
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800199 * Desired background color behind animation.
200 */
201 private int mBackgroundColor;
202
203 /**
Chet Haase48460322010-06-11 14:22:25 -0700204 * scalefactor to apply to pivot points, etc. during animation. Subclasses retrieve the
205 * value via getScaleFactor().
206 */
207 private float mScaleFactor = 1f;
208
Jorim Jaggi82c17862018-02-21 17:50:18 +0100209 private boolean mShowWallpaper;
Lucas Dupin3e1dc202018-12-02 15:14:20 -0800210 private boolean mHasRoundedCorners;
Jorim Jaggi82c17862018-02-21 17:50:18 +0100211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 private boolean mMore = true;
213 private boolean mOneMoreTime = true;
214
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100215 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 RectF mPreviousRegion = new RectF();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100217 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 RectF mRegion = new RectF();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100219 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 Transformation mTransformation = new Transformation();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100221 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 Transformation mPreviousTransformation = new Transformation();
223
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800224 private final CloseGuard guard = CloseGuard.get();
225
Romain Guy393a52c2012-05-22 20:21:08 -0700226 private Handler mListenerHandler;
227 private Runnable mOnStart;
228 private Runnable mOnRepeat;
229 private Runnable mOnEnd;
230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 /**
232 * Creates a new animation with a duration of 0ms, the default interpolator, with
233 * fillBefore set to true and fillAfter set to false
234 */
235 public Animation() {
236 ensureInterpolator();
237 }
238
239 /**
240 * Creates a new animation whose parameters come from the specified context and
241 * attributes set.
242 *
243 * @param context the application environment
244 * @param attrs the set of attributes holding the animation parameters
245 */
246 public Animation(Context context, AttributeSet attrs) {
247 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animation);
248
249 setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0));
250 setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0));
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled));
253 setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore));
254 setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter));
255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 setRepeatCount(a.getInt(com.android.internal.R.styleable.Animation_repeatCount, mRepeatCount));
257 setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART));
258
259 setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700260
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800261 setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));
262
Jorim Jaggi82c17862018-02-21 17:50:18 +0100263 setDetachWallpaper(
264 a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
265 setShowWallpaper(
266 a.getBoolean(com.android.internal.R.styleable.Animation_showWallpaper, false));
Lucas Dupin3e1dc202018-12-02 15:14:20 -0800267 setHasRoundedCorners(
268 a.getBoolean(com.android.internal.R.styleable.Animation_hasRoundedCorners, false));
Dianne Hackbornab0f4852011-09-12 16:59:06 -0700269
270 final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 a.recycle();
Dianne Hackbornab0f4852011-09-12 16:59:06 -0700273
274 if (resID > 0) {
275 setInterpolator(context, resID);
276 }
277
278 ensureInterpolator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
280
281 @Override
282 protected Animation clone() throws CloneNotSupportedException {
283 final Animation animation = (Animation) super.clone();
284 animation.mPreviousRegion = new RectF();
285 animation.mRegion = new RectF();
286 animation.mTransformation = new Transformation();
287 animation.mPreviousTransformation = new Transformation();
288 return animation;
289 }
290
291 /**
292 * Reset the initialization state of this animation.
293 *
294 * @see #initialize(int, int, int, int)
295 */
296 public void reset() {
297 mPreviousRegion.setEmpty();
298 mPreviousTransformation.clear();
299 mInitialized = false;
300 mCycleFlip = false;
301 mRepeated = 0;
302 mMore = true;
303 mOneMoreTime = true;
Romain Guy393a52c2012-05-22 20:21:08 -0700304 mListenerHandler = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 }
306
307 /**
Romain Guy305a2eb2010-02-09 11:30:44 -0800308 * Cancel the animation. Cancelling an animation invokes the animation
309 * listener, if set, to notify the end of the animation.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700310 *
Romain Guy305a2eb2010-02-09 11:30:44 -0800311 * If you cancel an animation manually, you must call {@link #reset()}
312 * before starting the animation again.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700313 *
314 * @see #reset()
315 * @see #start()
316 * @see #startNow()
Romain Guy305a2eb2010-02-09 11:30:44 -0800317 */
318 public void cancel() {
319 if (mStarted && !mEnded) {
Romain Guy393a52c2012-05-22 20:21:08 -0700320 fireAnimationEnd();
Romain Guy305a2eb2010-02-09 11:30:44 -0800321 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800322 guard.close();
Romain Guy305a2eb2010-02-09 11:30:44 -0800323 }
324 // Make sure we move the animation to the end
325 mStartTime = Long.MIN_VALUE;
326 mMore = mOneMoreTime = false;
327 }
328
329 /**
Romain Guyb4a107d2010-02-09 18:50:08 -0800330 * @hide
331 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100332 @UnsupportedAppUsage
Romain Guyb4a107d2010-02-09 18:50:08 -0800333 public void detach() {
334 if (mStarted && !mEnded) {
Romain Guyb4a107d2010-02-09 18:50:08 -0800335 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800336 guard.close();
Romain Guy393a52c2012-05-22 20:21:08 -0700337 fireAnimationEnd();
Romain Guyb4a107d2010-02-09 18:50:08 -0800338 }
339 }
340
341 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 * Whether or not the animation has been initialized.
343 *
344 * @return Has this animation been initialized.
345 * @see #initialize(int, int, int, int)
346 */
347 public boolean isInitialized() {
348 return mInitialized;
349 }
350
351 /**
352 * Initialize this animation with the dimensions of the object being
353 * animated as well as the objects parents. (This is to support animation
Chet Haase84c949f2011-12-20 10:38:31 -0800354 * sizes being specified relative to these dimensions.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 *
Chet Haase49afa5b2010-08-23 11:39:53 -0700356 * <p>Objects that interpret Animations should call this method when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 * the sizes of the object being animated and its parent are known, and
358 * before calling {@link #getTransformation}.
359 *
360 *
361 * @param width Width of the object being animated
362 * @param height Height of the object being animated
363 * @param parentWidth Width of the animated object's parent
364 * @param parentHeight Height of the animated object's parent
365 */
366 public void initialize(int width, int height, int parentWidth, int parentHeight) {
367 reset();
368 mInitialized = true;
369 }
370
371 /**
Romain Guy393a52c2012-05-22 20:21:08 -0700372 * Sets the handler used to invoke listeners.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700373 *
Romain Guy393a52c2012-05-22 20:21:08 -0700374 * @hide
375 */
376 public void setListenerHandler(Handler handler) {
377 if (mListenerHandler == null) {
378 mOnStart = new Runnable() {
379 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000380 dispatchAnimationStart();
Romain Guy393a52c2012-05-22 20:21:08 -0700381 }
382 };
383 mOnRepeat = new Runnable() {
384 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000385 dispatchAnimationRepeat();
Romain Guy393a52c2012-05-22 20:21:08 -0700386 }
387 };
388 mOnEnd = new Runnable() {
389 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000390 dispatchAnimationEnd();
Romain Guy393a52c2012-05-22 20:21:08 -0700391 }
392 };
393 }
394 mListenerHandler = handler;
395 }
396
397 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 * Sets the acceleration curve for this animation. The interpolator is loaded as
399 * a resource from the specified context.
400 *
401 * @param context The application environment
402 * @param resID The resource identifier of the interpolator to load
403 * @attr ref android.R.styleable#Animation_interpolator
404 */
Tor Norbyee8760542015-06-19 10:47:25 -0700405 public void setInterpolator(Context context, @AnimRes @InterpolatorRes int resID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 setInterpolator(AnimationUtils.loadInterpolator(context, resID));
407 }
408
409 /**
410 * Sets the acceleration curve for this animation. Defaults to a linear
411 * interpolation.
412 *
413 * @param i The interpolator which defines the acceleration curve
414 * @attr ref android.R.styleable#Animation_interpolator
415 */
416 public void setInterpolator(Interpolator i) {
417 mInterpolator = i;
418 }
419
420 /**
421 * When this animation should start relative to the start time. This is most
422 * useful when composing complex animations using an {@link AnimationSet }
423 * where some of the animations components start at different times.
424 *
425 * @param startOffset When this Animation should start, in milliseconds from
426 * the start time of the root AnimationSet.
427 * @attr ref android.R.styleable#Animation_startOffset
428 */
429 public void setStartOffset(long startOffset) {
430 mStartOffset = startOffset;
431 }
432
433 /**
434 * How long this animation should last. The duration cannot be negative.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700435 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * @param durationMillis Duration in milliseconds
437 *
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800438 * @throws java.lang.IllegalArgumentException if the duration is < 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 *
440 * @attr ref android.R.styleable#Animation_duration
441 */
442 public void setDuration(long durationMillis) {
443 if (durationMillis < 0) {
444 throw new IllegalArgumentException("Animation duration cannot be negative");
445 }
446 mDuration = durationMillis;
447 }
448
449 /**
450 * Ensure that the duration that this animation will run is not longer
451 * than <var>durationMillis</var>. In addition to adjusting the duration
452 * itself, this ensures that the repeat count also will not make it run
453 * longer than the given time.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700454 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 * @param durationMillis The maximum duration the animation is allowed
456 * to run.
457 */
458 public void restrictDuration(long durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800459 // If we start after the duration, then we just won't run.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 if (mStartOffset > durationMillis) {
461 mStartOffset = durationMillis;
462 mDuration = 0;
463 mRepeatCount = 0;
464 return;
465 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 long dur = mDuration + mStartOffset;
468 if (dur > durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800469 mDuration = durationMillis-mStartOffset;
470 dur = durationMillis;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800472 // If the duration is 0 or less, then we won't run.
473 if (mDuration <= 0) {
474 mDuration = 0;
475 mRepeatCount = 0;
476 return;
477 }
478 // Reduce the number of repeats to keep below the maximum duration.
479 // The comparison between mRepeatCount and duration is to catch
480 // overflows after multiplying them.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 if (mRepeatCount < 0 || mRepeatCount > durationMillis
482 || (dur*mRepeatCount) > durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800483 // Figure out how many times to do the animation. Subtract 1 since
484 // repeat count is the number of times to repeat so 0 runs once.
485 mRepeatCount = (int)(durationMillis/dur) - 1;
486 if (mRepeatCount < 0) {
487 mRepeatCount = 0;
488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 }
490 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 /**
493 * How much to scale the duration by.
494 *
495 * @param scale The amount to scale the duration.
496 */
497 public void scaleCurrentDuration(float scale) {
498 mDuration = (long) (mDuration * scale);
Dianne Hackborna4bacb82011-08-24 15:12:38 -0700499 mStartOffset = (long) (mStartOffset * scale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 }
501
502 /**
503 * When this animation should start. When the start time is set to
504 * {@link #START_ON_FIRST_FRAME}, the animation will start the first time
505 * {@link #getTransformation(long, Transformation)} is invoked. The time passed
506 * to this method should be obtained by calling
507 * {@link AnimationUtils#currentAnimationTimeMillis()} instead of
508 * {@link System#currentTimeMillis()}.
509 *
510 * @param startTimeMillis the start time in milliseconds
511 */
512 public void setStartTime(long startTimeMillis) {
513 mStartTime = startTimeMillis;
514 mStarted = mEnded = false;
515 mCycleFlip = false;
516 mRepeated = 0;
517 mMore = true;
518 }
519
520 /**
521 * Convenience method to start the animation the first time
522 * {@link #getTransformation(long, Transformation)} is invoked.
523 */
524 public void start() {
525 setStartTime(-1);
526 }
527
528 /**
529 * Convenience method to start the animation at the current time in
530 * milliseconds.
531 */
532 public void startNow() {
533 setStartTime(AnimationUtils.currentAnimationTimeMillis());
534 }
535
536 /**
537 * Defines what this animation should do when it reaches the end. This
538 * setting is applied only when the repeat count is either greater than
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700539 * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 *
541 * @param repeatMode {@link #RESTART} or {@link #REVERSE}
542 * @attr ref android.R.styleable#Animation_repeatMode
543 */
544 public void setRepeatMode(int repeatMode) {
545 mRepeatMode = repeatMode;
546 }
547
548 /**
549 * Sets how many times the animation should be repeated. If the repeat
550 * count is 0, the animation is never repeated. If the repeat count is
551 * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
The Android Open Source Project4df24232009-03-05 14:34:35 -0800552 * into account. The repeat count is 0 by default.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 *
554 * @param repeatCount the number of times the animation should be repeated
555 * @attr ref android.R.styleable#Animation_repeatCount
556 */
557 public void setRepeatCount(int repeatCount) {
558 if (repeatCount < 0) {
559 repeatCount = INFINITE;
560 }
561 mRepeatCount = repeatCount;
562 }
563
564 /**
Chet Haased8991c42011-08-24 07:20:53 -0700565 * If fillEnabled is true, this animation will apply the value of fillBefore.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 *
Chet Haased8991c42011-08-24 07:20:53 -0700567 * @return true if the animation will take fillBefore into account
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 * @attr ref android.R.styleable#Animation_fillEnabled
569 */
570 public boolean isFillEnabled() {
571 return mFillEnabled;
572 }
573
574 /**
Chet Haased8991c42011-08-24 07:20:53 -0700575 * If fillEnabled is true, the animation will apply the value of fillBefore.
576 * Otherwise, fillBefore is ignored and the animation
577 * transformation is always applied until the animation ends.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 *
Chet Haased8991c42011-08-24 07:20:53 -0700579 * @param fillEnabled true if the animation should take the value of fillBefore into account
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * @attr ref android.R.styleable#Animation_fillEnabled
581 *
582 * @see #setFillBefore(boolean)
583 * @see #setFillAfter(boolean)
584 */
585 public void setFillEnabled(boolean fillEnabled) {
586 mFillEnabled = fillEnabled;
587 }
588
589 /**
590 * If fillBefore is true, this animation will apply its transformation
Chet Haased8991c42011-08-24 07:20:53 -0700591 * before the start time of the animation. Defaults to true if
592 * {@link #setFillEnabled(boolean)} is not set to true.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 * Note that this applies when using an {@link
594 * android.view.animation.AnimationSet AnimationSet} to chain
595 * animations. The transformation is not applied before the AnimationSet
596 * itself starts.
597 *
598 * @param fillBefore true if the animation should apply its transformation before it starts
599 * @attr ref android.R.styleable#Animation_fillBefore
600 *
601 * @see #setFillEnabled(boolean)
602 */
603 public void setFillBefore(boolean fillBefore) {
604 mFillBefore = fillBefore;
605 }
606
607 /**
608 * If fillAfter is true, the transformation that this animation performed
609 * will persist when it is finished. Defaults to false if not set.
Chet Haased8991c42011-08-24 07:20:53 -0700610 * Note that this applies to individual animations and when using an {@link
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 * android.view.animation.AnimationSet AnimationSet} to chain
Chet Haased8991c42011-08-24 07:20:53 -0700612 * animations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 *
614 * @param fillAfter true if the animation should apply its transformation after it ends
615 * @attr ref android.R.styleable#Animation_fillAfter
616 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700617 * @see #setFillEnabled(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 */
619 public void setFillAfter(boolean fillAfter) {
620 mFillAfter = fillAfter;
621 }
622
623 /**
624 * Set the Z ordering mode to use while running the animation.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700625 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 * @param zAdjustment The desired mode, one of {@link #ZORDER_NORMAL},
627 * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
628 * @attr ref android.R.styleable#Animation_zAdjustment
629 */
630 public void setZAdjustment(int zAdjustment) {
631 mZAdjustment = zAdjustment;
632 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 /**
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800635 * Set background behind animation.
636 *
637 * @param bg The background color. If 0, no background. Currently must
638 * be black, with any desired alpha level.
639 */
Tor Norbye80756e32015-03-02 09:39:27 -0800640 public void setBackgroundColor(@ColorInt int bg) {
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800641 mBackgroundColor = bg;
642 }
643
644 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700645 * The scale factor is set by the call to <code>getTransformation</code>. Overrides of
Chet Haase48460322010-06-11 14:22:25 -0700646 * {@link #getTransformation(long, Transformation, float)} will get this value
647 * directly. Overrides of {@link #applyTransformation(float, Transformation)} can
648 * call this method to get the value.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700649 *
Chet Haase48460322010-06-11 14:22:25 -0700650 * @return float The scale factor that should be applied to pre-scaled values in
651 * an Animation such as the pivot points in {@link ScaleAnimation} and {@link RotateAnimation}.
652 */
653 protected float getScaleFactor() {
654 return mScaleFactor;
655 }
656
657 /**
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800658 * If detachWallpaper is true, and this is a window animation of a window
659 * that has a wallpaper background, then the window will be detached from
660 * the wallpaper while it runs. That is, the animation will only be applied
661 * to the window, and the wallpaper behind it will remain static.
662 *
663 * @param detachWallpaper true if the wallpaper should be detached from the animation
664 * @attr ref android.R.styleable#Animation_detachWallpaper
Jorim Jaggi8f520872018-08-14 17:00:20 +0200665 *
666 * @deprecated All window animations are running with detached wallpaper.
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800667 */
668 public void setDetachWallpaper(boolean detachWallpaper) {
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800669 }
670
671 /**
Jorim Jaggi82c17862018-02-21 17:50:18 +0100672 * If this animation is run as a window animation, this will make the wallpaper visible behind
673 * the animation.
674 *
675 * @param showWallpaper Whether the wallpaper should be shown during the animation.
676 * @attr ref android.R.styleable#Animation_detachWallpaper
677 * @hide
678 */
679 public void setShowWallpaper(boolean showWallpaper) {
680 mShowWallpaper = showWallpaper;
681 }
682
683 /**
Lucas Dupin3e1dc202018-12-02 15:14:20 -0800684 * If this is a window animation, the window will have rounded corners matching the display
685 * corner radius.
686 *
687 * @param hasRoundedCorners Whether the window should have rounded corners or not.
688 * @attr ref android.R.styleable#Animation_hasRoundedCorners
689 * @see com.android.internal.policy.ScreenDecorationsUtils#getWindowCornerRadius(Resources)
690 * @hide
691 */
692 public void setHasRoundedCorners(boolean hasRoundedCorners) {
693 mHasRoundedCorners = hasRoundedCorners;
694 }
695
696 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 * Gets the acceleration curve type for this animation.
698 *
699 * @return the {@link Interpolator} associated to this animation
700 * @attr ref android.R.styleable#Animation_interpolator
701 */
702 public Interpolator getInterpolator() {
703 return mInterpolator;
704 }
705
706 /**
707 * When this animation should start. If the animation has not startet yet,
708 * this method might return {@link #START_ON_FIRST_FRAME}.
709 *
710 * @return the time in milliseconds when the animation should start or
711 * {@link #START_ON_FIRST_FRAME}
712 */
713 public long getStartTime() {
714 return mStartTime;
715 }
716
717 /**
718 * How long this animation should last
719 *
720 * @return the duration in milliseconds of the animation
721 * @attr ref android.R.styleable#Animation_duration
722 */
723 public long getDuration() {
724 return mDuration;
725 }
726
727 /**
728 * When this animation should start, relative to StartTime
729 *
730 * @return the start offset in milliseconds
731 * @attr ref android.R.styleable#Animation_startOffset
732 */
733 public long getStartOffset() {
734 return mStartOffset;
735 }
736
737 /**
738 * Defines what this animation should do when it reaches the end.
739 *
740 * @return either one of {@link #REVERSE} or {@link #RESTART}
741 * @attr ref android.R.styleable#Animation_repeatMode
742 */
743 public int getRepeatMode() {
744 return mRepeatMode;
745 }
746
747 /**
748 * Defines how many times the animation should repeat. The default value
749 * is 0.
750 *
751 * @return the number of times the animation should repeat, or {@link #INFINITE}
752 * @attr ref android.R.styleable#Animation_repeatCount
753 */
754 public int getRepeatCount() {
755 return mRepeatCount;
756 }
757
758 /**
759 * If fillBefore is true, this animation will apply its transformation
Chet Haased8991c42011-08-24 07:20:53 -0700760 * before the start time of the animation. If fillBefore is false and
761 * {@link #isFillEnabled() fillEnabled} is true, the transformation will not be applied until
762 * the start time of the animation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 *
764 * @return true if the animation applies its transformation before it starts
765 * @attr ref android.R.styleable#Animation_fillBefore
766 */
767 public boolean getFillBefore() {
768 return mFillBefore;
769 }
770
771 /**
772 * If fillAfter is true, this animation will apply its transformation
773 * after the end time of the animation.
774 *
775 * @return true if the animation applies its transformation after it ends
776 * @attr ref android.R.styleable#Animation_fillAfter
777 */
778 public boolean getFillAfter() {
779 return mFillAfter;
780 }
781
782 /**
783 * Returns the Z ordering mode to use while running the animation as
784 * previously set by {@link #setZAdjustment}.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700785 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 * @return Returns one of {@link #ZORDER_NORMAL},
787 * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
788 * @attr ref android.R.styleable#Animation_zAdjustment
789 */
790 public int getZAdjustment() {
791 return mZAdjustment;
792 }
793
794 /**
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800795 * Returns the background color behind the animation.
796 */
Tor Norbye80756e32015-03-02 09:39:27 -0800797 @ColorInt
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800798 public int getBackgroundColor() {
799 return mBackgroundColor;
800 }
801
802 /**
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800803 * Return value of {@link #setDetachWallpaper(boolean)}.
804 * @attr ref android.R.styleable#Animation_detachWallpaper
Jorim Jaggi8f520872018-08-14 17:00:20 +0200805 *
806 * @deprecated All window animations are running with detached wallpaper.
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800807 */
808 public boolean getDetachWallpaper() {
Jorim Jaggi9fb93152019-01-10 16:25:49 +0100809 return true;
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800810 }
811
812 /**
Jorim Jaggi82c17862018-02-21 17:50:18 +0100813 * @return If run as a window animation, returns whether the wallpaper will be shown behind
814 * during the animation.
815 * @attr ref android.R.styleable#Animation_showWallpaper
816 * @hide
817 */
818 public boolean getShowWallpaper() {
819 return mShowWallpaper;
820 }
821
822 /**
Lucas Dupin3e1dc202018-12-02 15:14:20 -0800823 * @return if a window animation should have rounded corners or not.
824 *
825 * @attr ref android.R.styleable#Animation_hasRoundedCorners
826 * @hide
827 */
828 public boolean hasRoundedCorners() {
829 return mHasRoundedCorners;
830 }
831
832 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 * <p>Indicates whether or not this animation will affect the transformation
834 * matrix. For instance, a fade animation will not affect the matrix whereas
835 * a scale animation will.</p>
836 *
837 * @return true if this animation will change the transformation matrix
838 */
839 public boolean willChangeTransformationMatrix() {
840 // assume we will change the matrix
841 return true;
842 }
843
844 /**
845 * <p>Indicates whether or not this animation will affect the bounds of the
846 * animated view. For instance, a fade animation will not affect the bounds
847 * whereas a 200% scale animation will.</p>
848 *
849 * @return true if this animation will change the view's bounds
850 */
851 public boolean willChangeBounds() {
852 // assume we will change the bounds
853 return true;
854 }
855
Jelle Fresen65d21712018-11-30 10:23:25 +0000856 private boolean hasAnimationListener() {
Jelle Fresenb89473d2019-02-08 10:12:24 +0000857 return mListener != null;
Jelle Fresen65d21712018-11-30 10:23:25 +0000858 }
859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 /**
861 * <p>Binds an animation listener to this animation. The animation listener
862 * is notified of animation events such as the end of the animation or the
863 * repetition of the animation.</p>
864 *
865 * @param listener the animation listener to be notified
866 */
867 public void setAnimationListener(AnimationListener listener) {
868 mListener = listener;
869 }
870
871 /**
872 * Gurantees that this animation has an interpolator. Will use
873 * a AccelerateDecelerateInterpolator is nothing else was specified.
874 */
875 protected void ensureInterpolator() {
876 if (mInterpolator == null) {
877 mInterpolator = new AccelerateDecelerateInterpolator();
878 }
879 }
880
881 /**
882 * Compute a hint at how long the entire animation may last, in milliseconds.
883 * Animations can be written to cause themselves to run for a different
884 * duration than what is computed here, but generally this should be
885 * accurate.
886 */
887 public long computeDurationHint() {
888 return (getStartOffset() + getDuration()) * (getRepeatCount() + 1);
889 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 /**
892 * Gets the transformation to apply at a specified point in time. Implementations of this
893 * method should always replace the specified Transformation or document they are doing
894 * otherwise.
895 *
896 * @param currentTime Where we are in the animation. This is wall clock time.
Dianne Hackborn6908cd12010-11-08 15:11:16 -0800897 * @param outTransformation A transformation object that is provided by the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 * caller and will be filled in by the animation.
899 * @return True if the animation is still running
900 */
901 public boolean getTransformation(long currentTime, Transformation outTransformation) {
902 if (mStartTime == -1) {
903 mStartTime = currentTime;
904 }
905
906 final long startOffset = getStartOffset();
907 final long duration = mDuration;
908 float normalizedTime;
909 if (duration != 0) {
910 normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
911 (float) duration;
912 } else {
913 // time is a step-change with a zero duration
914 normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
915 }
916
Chet Haasef83464e2016-01-12 10:28:28 -0800917 final boolean expired = normalizedTime >= 1.0f || isCanceled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 mMore = !expired;
919
920 if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
921
922 if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
923 if (!mStarted) {
Romain Guy393a52c2012-05-22 20:21:08 -0700924 fireAnimationStart();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 mStarted = true;
Andreas Gampe56c560a2016-04-06 13:03:02 -0700926 if (NoImagePreloadHolder.USE_CLOSEGUARD) {
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800927 guard.open("cancel or detach or getTransformation");
928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 }
930
931 if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
932
933 if (mCycleFlip) {
934 normalizedTime = 1.0f - normalizedTime;
935 }
936
937 final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
938 applyTransformation(interpolatedTime, outTransformation);
939 }
940
941 if (expired) {
Chet Haasef83464e2016-01-12 10:28:28 -0800942 if (mRepeatCount == mRepeated || isCanceled()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 if (!mEnded) {
Romain Guy5180d1c2010-02-10 11:29:22 -0800944 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800945 guard.close();
Romain Guy393a52c2012-05-22 20:21:08 -0700946 fireAnimationEnd();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 }
948 } else {
949 if (mRepeatCount > 0) {
950 mRepeated++;
951 }
952
953 if (mRepeatMode == REVERSE) {
954 mCycleFlip = !mCycleFlip;
955 }
956
957 mStartTime = -1;
958 mMore = true;
959
Romain Guy393a52c2012-05-22 20:21:08 -0700960 fireAnimationRepeat();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 }
962 }
963
964 if (!mMore && mOneMoreTime) {
965 mOneMoreTime = false;
966 return true;
967 }
968
969 return mMore;
970 }
Romain Guy393a52c2012-05-22 20:21:08 -0700971
Chet Haasef83464e2016-01-12 10:28:28 -0800972 private boolean isCanceled() {
973 return mStartTime == Long.MIN_VALUE;
974 }
975
Romain Guy393a52c2012-05-22 20:21:08 -0700976 private void fireAnimationStart() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000977 if (hasAnimationListener()) {
978 if (mListenerHandler == null) dispatchAnimationStart();
Romain Guy393a52c2012-05-22 20:21:08 -0700979 else mListenerHandler.postAtFrontOfQueue(mOnStart);
980 }
981 }
982
983 private void fireAnimationRepeat() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000984 if (hasAnimationListener()) {
985 if (mListenerHandler == null) dispatchAnimationRepeat();
Romain Guy393a52c2012-05-22 20:21:08 -0700986 else mListenerHandler.postAtFrontOfQueue(mOnRepeat);
987 }
988 }
989
990 private void fireAnimationEnd() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000991 if (hasAnimationListener()) {
992 if (mListenerHandler == null) dispatchAnimationEnd();
Romain Guy393a52c2012-05-22 20:21:08 -0700993 else mListenerHandler.postAtFrontOfQueue(mOnEnd);
994 }
995 }
996
Jelle Fresen65d21712018-11-30 10:23:25 +0000997 void dispatchAnimationStart() {
998 if (mListener != null) {
999 mListener.onAnimationStart(this);
1000 }
Jelle Fresen65d21712018-11-30 10:23:25 +00001001 }
1002
1003 void dispatchAnimationRepeat() {
1004 if (mListener != null) {
1005 mListener.onAnimationRepeat(this);
1006 }
Jelle Fresen65d21712018-11-30 10:23:25 +00001007 }
1008
1009 void dispatchAnimationEnd() {
1010 if (mListener != null) {
1011 mListener.onAnimationEnd(this);
1012 }
Jelle Fresen65d21712018-11-30 10:23:25 +00001013 }
1014
Chet Haase48460322010-06-11 14:22:25 -07001015 /**
1016 * Gets the transformation to apply at a specified point in time. Implementations of this
1017 * method should always replace the specified Transformation or document they are doing
1018 * otherwise.
1019 *
1020 * @param currentTime Where we are in the animation. This is wall clock time.
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07001021 * @param outTransformation A transformation object that is provided by the
Chet Haase48460322010-06-11 14:22:25 -07001022 * caller and will be filled in by the animation.
1023 * @param scale Scaling factor to apply to any inputs to the transform operation, such
1024 * pivot points being rotated or scaled around.
1025 * @return True if the animation is still running
1026 */
1027 public boolean getTransformation(long currentTime, Transformation outTransformation,
1028 float scale) {
1029 mScaleFactor = scale;
1030 return getTransformation(currentTime, outTransformation);
1031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032
1033 /**
1034 * <p>Indicates whether this animation has started or not.</p>
1035 *
1036 * @return true if the animation has started, false otherwise
1037 */
1038 public boolean hasStarted() {
1039 return mStarted;
1040 }
1041
1042 /**
1043 * <p>Indicates whether this animation has ended or not.</p>
1044 *
1045 * @return true if the animation has ended, false otherwise
1046 */
1047 public boolean hasEnded() {
1048 return mEnded;
1049 }
1050
1051 /**
1052 * Helper for getTransformation. Subclasses should implement this to apply
1053 * their transforms given an interpolation value. Implementations of this
1054 * method should always replace the specified Transformation or document
1055 * they are doing otherwise.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001056 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 * @param interpolatedTime The value of the normalized time (0.0 to 1.0)
1058 * after it has been run through the interpolation function.
Robert Ly5c4d41e2012-02-22 11:05:55 -08001059 * @param t The Transformation object to fill in with the current
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 * transforms.
1061 */
1062 protected void applyTransformation(float interpolatedTime, Transformation t) {
1063 }
1064
1065 /**
1066 * Convert the information in the description of a size to an actual
1067 * dimension
1068 *
1069 * @param type One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
1070 * Animation.RELATIVE_TO_PARENT.
1071 * @param value The dimension associated with the type parameter
1072 * @param size The size of the object being animated
1073 * @param parentSize The size of the parent of the object being animated
1074 * @return The dimension to use for the animation
1075 */
1076 protected float resolveSize(int type, float value, int size, int parentSize) {
1077 switch (type) {
1078 case ABSOLUTE:
1079 return value;
1080 case RELATIVE_TO_SELF:
1081 return size * value;
1082 case RELATIVE_TO_PARENT:
1083 return parentSize * value;
1084 default:
1085 return value;
1086 }
1087 }
1088
1089 /**
1090 * @param left
1091 * @param top
1092 * @param right
1093 * @param bottom
1094 * @param invalidate
1095 * @param transformation
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001096 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 * @hide
1098 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +01001099 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 public void getInvalidateRegion(int left, int top, int right, int bottom,
1101 RectF invalidate, Transformation transformation) {
1102
1103 final RectF tempRegion = mRegion;
1104 final RectF previousRegion = mPreviousRegion;
1105
1106 invalidate.set(left, top, right, bottom);
1107 transformation.getMatrix().mapRect(invalidate);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001108 // Enlarge the invalidate region to account for rounding errors
1109 invalidate.inset(-1.0f, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 tempRegion.set(invalidate);
1111 invalidate.union(previousRegion);
1112
1113 previousRegion.set(tempRegion);
1114
1115 final Transformation tempTransformation = mTransformation;
1116 final Transformation previousTransformation = mPreviousTransformation;
1117
1118 tempTransformation.set(transformation);
1119 transformation.set(previousTransformation);
1120 previousTransformation.set(tempTransformation);
1121 }
1122
1123 /**
1124 * @param left
1125 * @param top
1126 * @param right
1127 * @param bottom
1128 *
1129 * @hide
1130 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +01001131 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
1133 final RectF region = mPreviousRegion;
1134 region.set(left, top, right, bottom);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001135 // Enlarge the invalidate region to account for rounding errors
1136 region.inset(-1.0f, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 if (mFillBefore) {
1138 final Transformation previousTransformation = mPreviousTransformation;
Andreas Agvard4766def2010-02-05 08:16:01 +01001139 applyTransformation(mInterpolator.getInterpolation(0.0f), previousTransformation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 }
1141 }
1142
Brian Carlstrom877e0b92010-11-19 14:04:05 -08001143 protected void finalize() throws Throwable {
1144 try {
1145 if (guard != null) {
1146 guard.warnIfOpen();
1147 }
1148 } finally {
1149 super.finalize();
1150 }
1151 }
1152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 /**
Romain Guyd4745a62011-07-22 16:03:07 -07001154 * Return true if this animation changes the view's alpha property.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001155 *
Romain Guyd4745a62011-07-22 16:03:07 -07001156 * @hide
1157 */
1158 public boolean hasAlpha() {
1159 return false;
1160 }
1161
1162 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 * Utility class to parse a string description of a size.
1164 */
1165 protected static class Description {
1166 /**
1167 * One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
1168 * Animation.RELATIVE_TO_PARENT.
1169 */
1170 public int type;
1171
1172 /**
1173 * The absolute or relative dimension for this Description.
1174 */
1175 public float value;
1176
1177 /**
1178 * Size descriptions can appear inthree forms:
1179 * <ol>
1180 * <li>An absolute size. This is represented by a number.</li>
1181 * <li>A size relative to the size of the object being animated. This
1182 * is represented by a number followed by "%".</li> *
1183 * <li>A size relative to the size of the parent of object being
1184 * animated. This is represented by a number followed by "%p".</li>
1185 * </ol>
1186 * @param value The typed value to parse
1187 * @return The parsed version of the description
1188 */
1189 static Description parseValue(TypedValue value) {
1190 Description d = new Description();
1191 if (value == null) {
1192 d.type = ABSOLUTE;
1193 d.value = 0;
1194 } else {
1195 if (value.type == TypedValue.TYPE_FRACTION) {
1196 d.type = (value.data & TypedValue.COMPLEX_UNIT_MASK) ==
1197 TypedValue.COMPLEX_UNIT_FRACTION_PARENT ?
1198 RELATIVE_TO_PARENT : RELATIVE_TO_SELF;
1199 d.value = TypedValue.complexToFloat(value.data);
1200 return d;
1201 } else if (value.type == TypedValue.TYPE_FLOAT) {
1202 d.type = ABSOLUTE;
1203 d.value = value.getFloat();
1204 return d;
1205 } else if (value.type >= TypedValue.TYPE_FIRST_INT &&
1206 value.type <= TypedValue.TYPE_LAST_INT) {
1207 d.type = ABSOLUTE;
1208 d.value = value.data;
1209 return d;
1210 }
1211 }
1212
1213 d.type = ABSOLUTE;
1214 d.value = 0.0f;
1215
1216 return d;
1217 }
1218 }
1219
1220 /**
1221 * <p>An animation listener receives notifications from an animation.
1222 * Notifications indicate animation related events, such as the end or the
1223 * repetition of the animation.</p>
1224 */
1225 public static interface AnimationListener {
1226 /**
1227 * <p>Notifies the start of the animation.</p>
1228 *
1229 * @param animation The started animation.
1230 */
1231 void onAnimationStart(Animation animation);
1232
1233 /**
1234 * <p>Notifies the end of the animation. This callback is not invoked
1235 * for animations with repeat count set to INFINITE.</p>
1236 *
1237 * @param animation The animation which reached its end.
1238 */
1239 void onAnimationEnd(Animation animation);
1240
1241 /**
1242 * <p>Notifies the repetition of the animation.</p>
1243 *
1244 * @param animation The animation which was repeated.
1245 */
1246 void onAnimationRepeat(Animation animation);
1247 }
1248}