blob: e0950948afb8b13524e76e3f633f6e53e641605a [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;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 private boolean mMore = true;
212 private boolean mOneMoreTime = true;
213
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100214 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 RectF mPreviousRegion = new RectF();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100216 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 RectF mRegion = new RectF();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100218 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 Transformation mTransformation = new Transformation();
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100220 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 Transformation mPreviousTransformation = new Transformation();
222
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800223 private final CloseGuard guard = CloseGuard.get();
224
Romain Guy393a52c2012-05-22 20:21:08 -0700225 private Handler mListenerHandler;
226 private Runnable mOnStart;
227 private Runnable mOnRepeat;
228 private Runnable mOnEnd;
229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 /**
231 * Creates a new animation with a duration of 0ms, the default interpolator, with
232 * fillBefore set to true and fillAfter set to false
233 */
234 public Animation() {
235 ensureInterpolator();
236 }
237
238 /**
239 * Creates a new animation whose parameters come from the specified context and
240 * attributes set.
241 *
242 * @param context the application environment
243 * @param attrs the set of attributes holding the animation parameters
244 */
245 public Animation(Context context, AttributeSet attrs) {
246 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animation);
247
248 setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0));
249 setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0));
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled));
252 setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore));
253 setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter));
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 setRepeatCount(a.getInt(com.android.internal.R.styleable.Animation_repeatCount, mRepeatCount));
256 setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART));
257
258 setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700259
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800260 setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));
261
Jorim Jaggi82c17862018-02-21 17:50:18 +0100262 setDetachWallpaper(
263 a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
264 setShowWallpaper(
265 a.getBoolean(com.android.internal.R.styleable.Animation_showWallpaper, false));
Dianne Hackbornab0f4852011-09-12 16:59:06 -0700266
267 final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 a.recycle();
Dianne Hackbornab0f4852011-09-12 16:59:06 -0700270
271 if (resID > 0) {
272 setInterpolator(context, resID);
273 }
274
275 ensureInterpolator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 }
277
278 @Override
279 protected Animation clone() throws CloneNotSupportedException {
280 final Animation animation = (Animation) super.clone();
281 animation.mPreviousRegion = new RectF();
282 animation.mRegion = new RectF();
283 animation.mTransformation = new Transformation();
284 animation.mPreviousTransformation = new Transformation();
285 return animation;
286 }
287
288 /**
289 * Reset the initialization state of this animation.
290 *
291 * @see #initialize(int, int, int, int)
292 */
293 public void reset() {
294 mPreviousRegion.setEmpty();
295 mPreviousTransformation.clear();
296 mInitialized = false;
297 mCycleFlip = false;
298 mRepeated = 0;
299 mMore = true;
300 mOneMoreTime = true;
Romain Guy393a52c2012-05-22 20:21:08 -0700301 mListenerHandler = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 }
303
304 /**
Romain Guy305a2eb2010-02-09 11:30:44 -0800305 * Cancel the animation. Cancelling an animation invokes the animation
306 * listener, if set, to notify the end of the animation.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700307 *
Romain Guy305a2eb2010-02-09 11:30:44 -0800308 * If you cancel an animation manually, you must call {@link #reset()}
309 * before starting the animation again.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700310 *
311 * @see #reset()
312 * @see #start()
313 * @see #startNow()
Romain Guy305a2eb2010-02-09 11:30:44 -0800314 */
315 public void cancel() {
316 if (mStarted && !mEnded) {
Romain Guy393a52c2012-05-22 20:21:08 -0700317 fireAnimationEnd();
Romain Guy305a2eb2010-02-09 11:30:44 -0800318 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800319 guard.close();
Romain Guy305a2eb2010-02-09 11:30:44 -0800320 }
321 // Make sure we move the animation to the end
322 mStartTime = Long.MIN_VALUE;
323 mMore = mOneMoreTime = false;
324 }
325
326 /**
Romain Guyb4a107d2010-02-09 18:50:08 -0800327 * @hide
328 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +0100329 @UnsupportedAppUsage
Romain Guyb4a107d2010-02-09 18:50:08 -0800330 public void detach() {
331 if (mStarted && !mEnded) {
Romain Guyb4a107d2010-02-09 18:50:08 -0800332 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800333 guard.close();
Romain Guy393a52c2012-05-22 20:21:08 -0700334 fireAnimationEnd();
Romain Guyb4a107d2010-02-09 18:50:08 -0800335 }
336 }
337
338 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 * Whether or not the animation has been initialized.
340 *
341 * @return Has this animation been initialized.
342 * @see #initialize(int, int, int, int)
343 */
344 public boolean isInitialized() {
345 return mInitialized;
346 }
347
348 /**
349 * Initialize this animation with the dimensions of the object being
350 * animated as well as the objects parents. (This is to support animation
Chet Haase84c949f2011-12-20 10:38:31 -0800351 * sizes being specified relative to these dimensions.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 *
Chet Haase49afa5b2010-08-23 11:39:53 -0700353 * <p>Objects that interpret Animations should call this method when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 * the sizes of the object being animated and its parent are known, and
355 * before calling {@link #getTransformation}.
356 *
357 *
358 * @param width Width of the object being animated
359 * @param height Height of the object being animated
360 * @param parentWidth Width of the animated object's parent
361 * @param parentHeight Height of the animated object's parent
362 */
363 public void initialize(int width, int height, int parentWidth, int parentHeight) {
364 reset();
365 mInitialized = true;
366 }
367
368 /**
Romain Guy393a52c2012-05-22 20:21:08 -0700369 * Sets the handler used to invoke listeners.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700370 *
Romain Guy393a52c2012-05-22 20:21:08 -0700371 * @hide
372 */
373 public void setListenerHandler(Handler handler) {
374 if (mListenerHandler == null) {
375 mOnStart = new Runnable() {
376 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000377 dispatchAnimationStart();
Romain Guy393a52c2012-05-22 20:21:08 -0700378 }
379 };
380 mOnRepeat = new Runnable() {
381 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000382 dispatchAnimationRepeat();
Romain Guy393a52c2012-05-22 20:21:08 -0700383 }
384 };
385 mOnEnd = new Runnable() {
386 public void run() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000387 dispatchAnimationEnd();
Romain Guy393a52c2012-05-22 20:21:08 -0700388 }
389 };
390 }
391 mListenerHandler = handler;
392 }
393
394 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 * Sets the acceleration curve for this animation. The interpolator is loaded as
396 * a resource from the specified context.
397 *
398 * @param context The application environment
399 * @param resID The resource identifier of the interpolator to load
400 * @attr ref android.R.styleable#Animation_interpolator
401 */
Tor Norbyee8760542015-06-19 10:47:25 -0700402 public void setInterpolator(Context context, @AnimRes @InterpolatorRes int resID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 setInterpolator(AnimationUtils.loadInterpolator(context, resID));
404 }
405
406 /**
407 * Sets the acceleration curve for this animation. Defaults to a linear
408 * interpolation.
409 *
410 * @param i The interpolator which defines the acceleration curve
411 * @attr ref android.R.styleable#Animation_interpolator
412 */
413 public void setInterpolator(Interpolator i) {
414 mInterpolator = i;
415 }
416
417 /**
418 * When this animation should start relative to the start time. This is most
419 * useful when composing complex animations using an {@link AnimationSet }
420 * where some of the animations components start at different times.
421 *
422 * @param startOffset When this Animation should start, in milliseconds from
423 * the start time of the root AnimationSet.
424 * @attr ref android.R.styleable#Animation_startOffset
425 */
426 public void setStartOffset(long startOffset) {
427 mStartOffset = startOffset;
428 }
429
430 /**
431 * How long this animation should last. The duration cannot be negative.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700432 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * @param durationMillis Duration in milliseconds
434 *
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800435 * @throws java.lang.IllegalArgumentException if the duration is < 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 *
437 * @attr ref android.R.styleable#Animation_duration
438 */
439 public void setDuration(long durationMillis) {
440 if (durationMillis < 0) {
441 throw new IllegalArgumentException("Animation duration cannot be negative");
442 }
443 mDuration = durationMillis;
444 }
445
446 /**
447 * Ensure that the duration that this animation will run is not longer
448 * than <var>durationMillis</var>. In addition to adjusting the duration
449 * itself, this ensures that the repeat count also will not make it run
450 * longer than the given time.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700451 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 * @param durationMillis The maximum duration the animation is allowed
453 * to run.
454 */
455 public void restrictDuration(long durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800456 // If we start after the duration, then we just won't run.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 if (mStartOffset > durationMillis) {
458 mStartOffset = durationMillis;
459 mDuration = 0;
460 mRepeatCount = 0;
461 return;
462 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 long dur = mDuration + mStartOffset;
465 if (dur > durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800466 mDuration = durationMillis-mStartOffset;
467 dur = durationMillis;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800469 // If the duration is 0 or less, then we won't run.
470 if (mDuration <= 0) {
471 mDuration = 0;
472 mRepeatCount = 0;
473 return;
474 }
475 // Reduce the number of repeats to keep below the maximum duration.
476 // The comparison between mRepeatCount and duration is to catch
477 // overflows after multiplying them.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 if (mRepeatCount < 0 || mRepeatCount > durationMillis
479 || (dur*mRepeatCount) > durationMillis) {
The Android Open Source Project4df24232009-03-05 14:34:35 -0800480 // Figure out how many times to do the animation. Subtract 1 since
481 // repeat count is the number of times to repeat so 0 runs once.
482 mRepeatCount = (int)(durationMillis/dur) - 1;
483 if (mRepeatCount < 0) {
484 mRepeatCount = 0;
485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 /**
490 * How much to scale the duration by.
491 *
492 * @param scale The amount to scale the duration.
493 */
494 public void scaleCurrentDuration(float scale) {
495 mDuration = (long) (mDuration * scale);
Dianne Hackborna4bacb82011-08-24 15:12:38 -0700496 mStartOffset = (long) (mStartOffset * scale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
498
499 /**
500 * When this animation should start. When the start time is set to
501 * {@link #START_ON_FIRST_FRAME}, the animation will start the first time
502 * {@link #getTransformation(long, Transformation)} is invoked. The time passed
503 * to this method should be obtained by calling
504 * {@link AnimationUtils#currentAnimationTimeMillis()} instead of
505 * {@link System#currentTimeMillis()}.
506 *
507 * @param startTimeMillis the start time in milliseconds
508 */
509 public void setStartTime(long startTimeMillis) {
510 mStartTime = startTimeMillis;
511 mStarted = mEnded = false;
512 mCycleFlip = false;
513 mRepeated = 0;
514 mMore = true;
515 }
516
517 /**
518 * Convenience method to start the animation the first time
519 * {@link #getTransformation(long, Transformation)} is invoked.
520 */
521 public void start() {
522 setStartTime(-1);
523 }
524
525 /**
526 * Convenience method to start the animation at the current time in
527 * milliseconds.
528 */
529 public void startNow() {
530 setStartTime(AnimationUtils.currentAnimationTimeMillis());
531 }
532
533 /**
534 * Defines what this animation should do when it reaches the end. This
535 * setting is applied only when the repeat count is either greater than
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700536 * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 *
538 * @param repeatMode {@link #RESTART} or {@link #REVERSE}
539 * @attr ref android.R.styleable#Animation_repeatMode
540 */
541 public void setRepeatMode(int repeatMode) {
542 mRepeatMode = repeatMode;
543 }
544
545 /**
546 * Sets how many times the animation should be repeated. If the repeat
547 * count is 0, the animation is never repeated. If the repeat count is
548 * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
The Android Open Source Project4df24232009-03-05 14:34:35 -0800549 * into account. The repeat count is 0 by default.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 *
551 * @param repeatCount the number of times the animation should be repeated
552 * @attr ref android.R.styleable#Animation_repeatCount
553 */
554 public void setRepeatCount(int repeatCount) {
555 if (repeatCount < 0) {
556 repeatCount = INFINITE;
557 }
558 mRepeatCount = repeatCount;
559 }
560
561 /**
Chet Haased8991c42011-08-24 07:20:53 -0700562 * If fillEnabled is true, this animation will apply the value of fillBefore.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 *
Chet Haased8991c42011-08-24 07:20:53 -0700564 * @return true if the animation will take fillBefore into account
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 * @attr ref android.R.styleable#Animation_fillEnabled
566 */
567 public boolean isFillEnabled() {
568 return mFillEnabled;
569 }
570
571 /**
Chet Haased8991c42011-08-24 07:20:53 -0700572 * If fillEnabled is true, the animation will apply the value of fillBefore.
573 * Otherwise, fillBefore is ignored and the animation
574 * transformation is always applied until the animation ends.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 *
Chet Haased8991c42011-08-24 07:20:53 -0700576 * @param fillEnabled true if the animation should take the value of fillBefore into account
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 * @attr ref android.R.styleable#Animation_fillEnabled
578 *
579 * @see #setFillBefore(boolean)
580 * @see #setFillAfter(boolean)
581 */
582 public void setFillEnabled(boolean fillEnabled) {
583 mFillEnabled = fillEnabled;
584 }
585
586 /**
587 * If fillBefore is true, this animation will apply its transformation
Chet Haased8991c42011-08-24 07:20:53 -0700588 * before the start time of the animation. Defaults to true if
589 * {@link #setFillEnabled(boolean)} is not set to true.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 * Note that this applies when using an {@link
591 * android.view.animation.AnimationSet AnimationSet} to chain
592 * animations. The transformation is not applied before the AnimationSet
593 * itself starts.
594 *
595 * @param fillBefore true if the animation should apply its transformation before it starts
596 * @attr ref android.R.styleable#Animation_fillBefore
597 *
598 * @see #setFillEnabled(boolean)
599 */
600 public void setFillBefore(boolean fillBefore) {
601 mFillBefore = fillBefore;
602 }
603
604 /**
605 * If fillAfter is true, the transformation that this animation performed
606 * will persist when it is finished. Defaults to false if not set.
Chet Haased8991c42011-08-24 07:20:53 -0700607 * Note that this applies to individual animations and when using an {@link
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 * android.view.animation.AnimationSet AnimationSet} to chain
Chet Haased8991c42011-08-24 07:20:53 -0700609 * animations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 *
611 * @param fillAfter true if the animation should apply its transformation after it ends
612 * @attr ref android.R.styleable#Animation_fillAfter
613 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700614 * @see #setFillEnabled(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 */
616 public void setFillAfter(boolean fillAfter) {
617 mFillAfter = fillAfter;
618 }
619
620 /**
621 * Set the Z ordering mode to use while running the animation.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700622 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 * @param zAdjustment The desired mode, one of {@link #ZORDER_NORMAL},
624 * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
625 * @attr ref android.R.styleable#Animation_zAdjustment
626 */
627 public void setZAdjustment(int zAdjustment) {
628 mZAdjustment = zAdjustment;
629 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 /**
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800632 * Set background behind animation.
633 *
634 * @param bg The background color. If 0, no background. Currently must
635 * be black, with any desired alpha level.
636 */
Tor Norbye80756e32015-03-02 09:39:27 -0800637 public void setBackgroundColor(@ColorInt int bg) {
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800638 mBackgroundColor = bg;
639 }
640
641 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700642 * The scale factor is set by the call to <code>getTransformation</code>. Overrides of
Chet Haase48460322010-06-11 14:22:25 -0700643 * {@link #getTransformation(long, Transformation, float)} will get this value
644 * directly. Overrides of {@link #applyTransformation(float, Transformation)} can
645 * call this method to get the value.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700646 *
Chet Haase48460322010-06-11 14:22:25 -0700647 * @return float The scale factor that should be applied to pre-scaled values in
648 * an Animation such as the pivot points in {@link ScaleAnimation} and {@link RotateAnimation}.
649 */
650 protected float getScaleFactor() {
651 return mScaleFactor;
652 }
653
654 /**
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800655 * If detachWallpaper is true, and this is a window animation of a window
656 * that has a wallpaper background, then the window will be detached from
657 * the wallpaper while it runs. That is, the animation will only be applied
658 * to the window, and the wallpaper behind it will remain static.
659 *
660 * @param detachWallpaper true if the wallpaper should be detached from the animation
661 * @attr ref android.R.styleable#Animation_detachWallpaper
Jorim Jaggi8f520872018-08-14 17:00:20 +0200662 *
663 * @deprecated All window animations are running with detached wallpaper.
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800664 */
665 public void setDetachWallpaper(boolean detachWallpaper) {
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800666 }
667
668 /**
Jorim Jaggi82c17862018-02-21 17:50:18 +0100669 * If this animation is run as a window animation, this will make the wallpaper visible behind
670 * the animation.
671 *
672 * @param showWallpaper Whether the wallpaper should be shown during the animation.
673 * @attr ref android.R.styleable#Animation_detachWallpaper
674 * @hide
675 */
676 public void setShowWallpaper(boolean showWallpaper) {
677 mShowWallpaper = showWallpaper;
678 }
679
680 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 * Gets the acceleration curve type for this animation.
682 *
683 * @return the {@link Interpolator} associated to this animation
684 * @attr ref android.R.styleable#Animation_interpolator
685 */
686 public Interpolator getInterpolator() {
687 return mInterpolator;
688 }
689
690 /**
691 * When this animation should start. If the animation has not startet yet,
692 * this method might return {@link #START_ON_FIRST_FRAME}.
693 *
694 * @return the time in milliseconds when the animation should start or
695 * {@link #START_ON_FIRST_FRAME}
696 */
697 public long getStartTime() {
698 return mStartTime;
699 }
700
701 /**
702 * How long this animation should last
703 *
704 * @return the duration in milliseconds of the animation
705 * @attr ref android.R.styleable#Animation_duration
706 */
707 public long getDuration() {
708 return mDuration;
709 }
710
711 /**
712 * When this animation should start, relative to StartTime
713 *
714 * @return the start offset in milliseconds
715 * @attr ref android.R.styleable#Animation_startOffset
716 */
717 public long getStartOffset() {
718 return mStartOffset;
719 }
720
721 /**
722 * Defines what this animation should do when it reaches the end.
723 *
724 * @return either one of {@link #REVERSE} or {@link #RESTART}
725 * @attr ref android.R.styleable#Animation_repeatMode
726 */
727 public int getRepeatMode() {
728 return mRepeatMode;
729 }
730
731 /**
732 * Defines how many times the animation should repeat. The default value
733 * is 0.
734 *
735 * @return the number of times the animation should repeat, or {@link #INFINITE}
736 * @attr ref android.R.styleable#Animation_repeatCount
737 */
738 public int getRepeatCount() {
739 return mRepeatCount;
740 }
741
742 /**
743 * If fillBefore is true, this animation will apply its transformation
Chet Haased8991c42011-08-24 07:20:53 -0700744 * before the start time of the animation. If fillBefore is false and
745 * {@link #isFillEnabled() fillEnabled} is true, the transformation will not be applied until
746 * the start time of the animation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 *
748 * @return true if the animation applies its transformation before it starts
749 * @attr ref android.R.styleable#Animation_fillBefore
750 */
751 public boolean getFillBefore() {
752 return mFillBefore;
753 }
754
755 /**
756 * If fillAfter is true, this animation will apply its transformation
757 * after the end time of the animation.
758 *
759 * @return true if the animation applies its transformation after it ends
760 * @attr ref android.R.styleable#Animation_fillAfter
761 */
762 public boolean getFillAfter() {
763 return mFillAfter;
764 }
765
766 /**
767 * Returns the Z ordering mode to use while running the animation as
768 * previously set by {@link #setZAdjustment}.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700769 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 * @return Returns one of {@link #ZORDER_NORMAL},
771 * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
772 * @attr ref android.R.styleable#Animation_zAdjustment
773 */
774 public int getZAdjustment() {
775 return mZAdjustment;
776 }
777
778 /**
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800779 * Returns the background color behind the animation.
780 */
Tor Norbye80756e32015-03-02 09:39:27 -0800781 @ColorInt
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800782 public int getBackgroundColor() {
783 return mBackgroundColor;
784 }
785
786 /**
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800787 * Return value of {@link #setDetachWallpaper(boolean)}.
788 * @attr ref android.R.styleable#Animation_detachWallpaper
Jorim Jaggi8f520872018-08-14 17:00:20 +0200789 *
790 * @deprecated All window animations are running with detached wallpaper.
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800791 */
792 public boolean getDetachWallpaper() {
Jorim Jaggi9fb93152019-01-10 16:25:49 +0100793 return true;
Jean-Baptiste Queru9db3d072009-11-12 18:45:53 -0800794 }
795
796 /**
Jorim Jaggi82c17862018-02-21 17:50:18 +0100797 * @return If run as a window animation, returns whether the wallpaper will be shown behind
798 * during the animation.
799 * @attr ref android.R.styleable#Animation_showWallpaper
800 * @hide
801 */
802 public boolean getShowWallpaper() {
803 return mShowWallpaper;
804 }
805
806 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 * <p>Indicates whether or not this animation will affect the transformation
808 * matrix. For instance, a fade animation will not affect the matrix whereas
809 * a scale animation will.</p>
810 *
811 * @return true if this animation will change the transformation matrix
812 */
813 public boolean willChangeTransformationMatrix() {
814 // assume we will change the matrix
815 return true;
816 }
817
818 /**
819 * <p>Indicates whether or not this animation will affect the bounds of the
820 * animated view. For instance, a fade animation will not affect the bounds
821 * whereas a 200% scale animation will.</p>
822 *
823 * @return true if this animation will change the view's bounds
824 */
825 public boolean willChangeBounds() {
826 // assume we will change the bounds
827 return true;
828 }
829
Jelle Fresen65d21712018-11-30 10:23:25 +0000830 private boolean hasAnimationListener() {
Jelle Fresenb89473d2019-02-08 10:12:24 +0000831 return mListener != null;
Jelle Fresen65d21712018-11-30 10:23:25 +0000832 }
833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 /**
835 * <p>Binds an animation listener to this animation. The animation listener
836 * is notified of animation events such as the end of the animation or the
837 * repetition of the animation.</p>
838 *
839 * @param listener the animation listener to be notified
840 */
841 public void setAnimationListener(AnimationListener listener) {
842 mListener = listener;
843 }
844
845 /**
846 * Gurantees that this animation has an interpolator. Will use
847 * a AccelerateDecelerateInterpolator is nothing else was specified.
848 */
849 protected void ensureInterpolator() {
850 if (mInterpolator == null) {
851 mInterpolator = new AccelerateDecelerateInterpolator();
852 }
853 }
854
855 /**
856 * Compute a hint at how long the entire animation may last, in milliseconds.
857 * Animations can be written to cause themselves to run for a different
858 * duration than what is computed here, but generally this should be
859 * accurate.
860 */
861 public long computeDurationHint() {
862 return (getStartOffset() + getDuration()) * (getRepeatCount() + 1);
863 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 /**
866 * Gets the transformation to apply at a specified point in time. Implementations of this
867 * method should always replace the specified Transformation or document they are doing
868 * otherwise.
869 *
870 * @param currentTime Where we are in the animation. This is wall clock time.
Dianne Hackborn6908cd12010-11-08 15:11:16 -0800871 * @param outTransformation A transformation object that is provided by the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 * caller and will be filled in by the animation.
873 * @return True if the animation is still running
874 */
875 public boolean getTransformation(long currentTime, Transformation outTransformation) {
876 if (mStartTime == -1) {
877 mStartTime = currentTime;
878 }
879
880 final long startOffset = getStartOffset();
881 final long duration = mDuration;
882 float normalizedTime;
883 if (duration != 0) {
884 normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
885 (float) duration;
886 } else {
887 // time is a step-change with a zero duration
888 normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
889 }
890
Chet Haasef83464e2016-01-12 10:28:28 -0800891 final boolean expired = normalizedTime >= 1.0f || isCanceled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 mMore = !expired;
893
894 if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
895
896 if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
897 if (!mStarted) {
Romain Guy393a52c2012-05-22 20:21:08 -0700898 fireAnimationStart();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 mStarted = true;
Andreas Gampe56c560a2016-04-06 13:03:02 -0700900 if (NoImagePreloadHolder.USE_CLOSEGUARD) {
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800901 guard.open("cancel or detach or getTransformation");
902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 }
904
905 if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
906
907 if (mCycleFlip) {
908 normalizedTime = 1.0f - normalizedTime;
909 }
910
911 final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
912 applyTransformation(interpolatedTime, outTransformation);
913 }
914
915 if (expired) {
Chet Haasef83464e2016-01-12 10:28:28 -0800916 if (mRepeatCount == mRepeated || isCanceled()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 if (!mEnded) {
Romain Guy5180d1c2010-02-10 11:29:22 -0800918 mEnded = true;
Brian Carlstrom877e0b92010-11-19 14:04:05 -0800919 guard.close();
Romain Guy393a52c2012-05-22 20:21:08 -0700920 fireAnimationEnd();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 }
922 } else {
923 if (mRepeatCount > 0) {
924 mRepeated++;
925 }
926
927 if (mRepeatMode == REVERSE) {
928 mCycleFlip = !mCycleFlip;
929 }
930
931 mStartTime = -1;
932 mMore = true;
933
Romain Guy393a52c2012-05-22 20:21:08 -0700934 fireAnimationRepeat();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 }
936 }
937
938 if (!mMore && mOneMoreTime) {
939 mOneMoreTime = false;
940 return true;
941 }
942
943 return mMore;
944 }
Romain Guy393a52c2012-05-22 20:21:08 -0700945
Chet Haasef83464e2016-01-12 10:28:28 -0800946 private boolean isCanceled() {
947 return mStartTime == Long.MIN_VALUE;
948 }
949
Romain Guy393a52c2012-05-22 20:21:08 -0700950 private void fireAnimationStart() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000951 if (hasAnimationListener()) {
952 if (mListenerHandler == null) dispatchAnimationStart();
Romain Guy393a52c2012-05-22 20:21:08 -0700953 else mListenerHandler.postAtFrontOfQueue(mOnStart);
954 }
955 }
956
957 private void fireAnimationRepeat() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000958 if (hasAnimationListener()) {
959 if (mListenerHandler == null) dispatchAnimationRepeat();
Romain Guy393a52c2012-05-22 20:21:08 -0700960 else mListenerHandler.postAtFrontOfQueue(mOnRepeat);
961 }
962 }
963
964 private void fireAnimationEnd() {
Jelle Fresen65d21712018-11-30 10:23:25 +0000965 if (hasAnimationListener()) {
966 if (mListenerHandler == null) dispatchAnimationEnd();
Romain Guy393a52c2012-05-22 20:21:08 -0700967 else mListenerHandler.postAtFrontOfQueue(mOnEnd);
968 }
969 }
970
Jelle Fresen65d21712018-11-30 10:23:25 +0000971 void dispatchAnimationStart() {
972 if (mListener != null) {
973 mListener.onAnimationStart(this);
974 }
Jelle Fresen65d21712018-11-30 10:23:25 +0000975 }
976
977 void dispatchAnimationRepeat() {
978 if (mListener != null) {
979 mListener.onAnimationRepeat(this);
980 }
Jelle Fresen65d21712018-11-30 10:23:25 +0000981 }
982
983 void dispatchAnimationEnd() {
984 if (mListener != null) {
985 mListener.onAnimationEnd(this);
986 }
Jelle Fresen65d21712018-11-30 10:23:25 +0000987 }
988
Chet Haase48460322010-06-11 14:22:25 -0700989 /**
990 * Gets the transformation to apply at a specified point in time. Implementations of this
991 * method should always replace the specified Transformation or document they are doing
992 * otherwise.
993 *
994 * @param currentTime Where we are in the animation. This is wall clock time.
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700995 * @param outTransformation A transformation object that is provided by the
Chet Haase48460322010-06-11 14:22:25 -0700996 * caller and will be filled in by the animation.
997 * @param scale Scaling factor to apply to any inputs to the transform operation, such
998 * pivot points being rotated or scaled around.
999 * @return True if the animation is still running
1000 */
1001 public boolean getTransformation(long currentTime, Transformation outTransformation,
1002 float scale) {
1003 mScaleFactor = scale;
1004 return getTransformation(currentTime, outTransformation);
1005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006
1007 /**
1008 * <p>Indicates whether this animation has started or not.</p>
1009 *
1010 * @return true if the animation has started, false otherwise
1011 */
1012 public boolean hasStarted() {
1013 return mStarted;
1014 }
1015
1016 /**
1017 * <p>Indicates whether this animation has ended or not.</p>
1018 *
1019 * @return true if the animation has ended, false otherwise
1020 */
1021 public boolean hasEnded() {
1022 return mEnded;
1023 }
1024
1025 /**
1026 * Helper for getTransformation. Subclasses should implement this to apply
1027 * their transforms given an interpolation value. Implementations of this
1028 * method should always replace the specified Transformation or document
1029 * they are doing otherwise.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001030 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 * @param interpolatedTime The value of the normalized time (0.0 to 1.0)
1032 * after it has been run through the interpolation function.
Robert Ly5c4d41e2012-02-22 11:05:55 -08001033 * @param t The Transformation object to fill in with the current
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 * transforms.
1035 */
1036 protected void applyTransformation(float interpolatedTime, Transformation t) {
1037 }
1038
1039 /**
1040 * Convert the information in the description of a size to an actual
1041 * dimension
1042 *
1043 * @param type One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
1044 * Animation.RELATIVE_TO_PARENT.
1045 * @param value The dimension associated with the type parameter
1046 * @param size The size of the object being animated
1047 * @param parentSize The size of the parent of the object being animated
1048 * @return The dimension to use for the animation
1049 */
1050 protected float resolveSize(int type, float value, int size, int parentSize) {
1051 switch (type) {
1052 case ABSOLUTE:
1053 return value;
1054 case RELATIVE_TO_SELF:
1055 return size * value;
1056 case RELATIVE_TO_PARENT:
1057 return parentSize * value;
1058 default:
1059 return value;
1060 }
1061 }
1062
1063 /**
1064 * @param left
1065 * @param top
1066 * @param right
1067 * @param bottom
1068 * @param invalidate
1069 * @param transformation
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001070 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 * @hide
1072 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +01001073 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 public void getInvalidateRegion(int left, int top, int right, int bottom,
1075 RectF invalidate, Transformation transformation) {
1076
1077 final RectF tempRegion = mRegion;
1078 final RectF previousRegion = mPreviousRegion;
1079
1080 invalidate.set(left, top, right, bottom);
1081 transformation.getMatrix().mapRect(invalidate);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001082 // Enlarge the invalidate region to account for rounding errors
1083 invalidate.inset(-1.0f, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 tempRegion.set(invalidate);
1085 invalidate.union(previousRegion);
1086
1087 previousRegion.set(tempRegion);
1088
1089 final Transformation tempTransformation = mTransformation;
1090 final Transformation previousTransformation = mPreviousTransformation;
1091
1092 tempTransformation.set(transformation);
1093 transformation.set(previousTransformation);
1094 previousTransformation.set(tempTransformation);
1095 }
1096
1097 /**
1098 * @param left
1099 * @param top
1100 * @param right
1101 * @param bottom
1102 *
1103 * @hide
1104 */
Mathew Inwoodfb75be92018-07-27 14:34:22 +01001105 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
1107 final RectF region = mPreviousRegion;
1108 region.set(left, top, right, bottom);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001109 // Enlarge the invalidate region to account for rounding errors
1110 region.inset(-1.0f, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 if (mFillBefore) {
1112 final Transformation previousTransformation = mPreviousTransformation;
Andreas Agvard4766def2010-02-05 08:16:01 +01001113 applyTransformation(mInterpolator.getInterpolation(0.0f), previousTransformation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 }
1115 }
1116
Brian Carlstrom877e0b92010-11-19 14:04:05 -08001117 protected void finalize() throws Throwable {
1118 try {
1119 if (guard != null) {
1120 guard.warnIfOpen();
1121 }
1122 } finally {
1123 super.finalize();
1124 }
1125 }
1126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 /**
Romain Guyd4745a62011-07-22 16:03:07 -07001128 * Return true if this animation changes the view's alpha property.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001129 *
Romain Guyd4745a62011-07-22 16:03:07 -07001130 * @hide
1131 */
1132 public boolean hasAlpha() {
1133 return false;
1134 }
1135
1136 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 * Utility class to parse a string description of a size.
1138 */
1139 protected static class Description {
1140 /**
1141 * One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
1142 * Animation.RELATIVE_TO_PARENT.
1143 */
1144 public int type;
1145
1146 /**
1147 * The absolute or relative dimension for this Description.
1148 */
1149 public float value;
1150
1151 /**
1152 * Size descriptions can appear inthree forms:
1153 * <ol>
1154 * <li>An absolute size. This is represented by a number.</li>
1155 * <li>A size relative to the size of the object being animated. This
1156 * is represented by a number followed by "%".</li> *
1157 * <li>A size relative to the size of the parent of object being
1158 * animated. This is represented by a number followed by "%p".</li>
1159 * </ol>
1160 * @param value The typed value to parse
1161 * @return The parsed version of the description
1162 */
1163 static Description parseValue(TypedValue value) {
1164 Description d = new Description();
1165 if (value == null) {
1166 d.type = ABSOLUTE;
1167 d.value = 0;
1168 } else {
1169 if (value.type == TypedValue.TYPE_FRACTION) {
1170 d.type = (value.data & TypedValue.COMPLEX_UNIT_MASK) ==
1171 TypedValue.COMPLEX_UNIT_FRACTION_PARENT ?
1172 RELATIVE_TO_PARENT : RELATIVE_TO_SELF;
1173 d.value = TypedValue.complexToFloat(value.data);
1174 return d;
1175 } else if (value.type == TypedValue.TYPE_FLOAT) {
1176 d.type = ABSOLUTE;
1177 d.value = value.getFloat();
1178 return d;
1179 } else if (value.type >= TypedValue.TYPE_FIRST_INT &&
1180 value.type <= TypedValue.TYPE_LAST_INT) {
1181 d.type = ABSOLUTE;
1182 d.value = value.data;
1183 return d;
1184 }
1185 }
1186
1187 d.type = ABSOLUTE;
1188 d.value = 0.0f;
1189
1190 return d;
1191 }
1192 }
1193
1194 /**
1195 * <p>An animation listener receives notifications from an animation.
1196 * Notifications indicate animation related events, such as the end or the
1197 * repetition of the animation.</p>
1198 */
1199 public static interface AnimationListener {
1200 /**
1201 * <p>Notifies the start of the animation.</p>
1202 *
1203 * @param animation The started animation.
1204 */
1205 void onAnimationStart(Animation animation);
1206
1207 /**
1208 * <p>Notifies the end of the animation. This callback is not invoked
1209 * for animations with repeat count set to INFINITE.</p>
1210 *
1211 * @param animation The animation which reached its end.
1212 */
1213 void onAnimationEnd(Animation animation);
1214
1215 /**
1216 * <p>Notifies the repetition of the animation.</p>
1217 *
1218 * @param animation The animation which was repeated.
1219 */
1220 void onAnimationRepeat(Animation animation);
1221 }
1222}