New functionalities for AnimatorSet: Reverse, Seek
This CL adds reverse and seek to AnimatorSet's capabilities. Structural changes: 1) Child animators are now being pulsed by AnimatorSet in a more timeline manner, as opposed to the old listener based style. This timeline based approach avoids the time offset in between sequential animations, and therefore produces a more accurate overall duration. 2) Timeline is done by representing start and end of each child animator in two separate events. All the events are then sorted based on the time they happen, such that it's clear what should happen in between last frame and the new frame (i.e. which animations should start or end). Test: CTS (in the same topic branch) Bug: 30993532 Change-Id: If1dc6e8dbc93a4bf5ade8c5b0dcf43d3ee6ba7b5
This commit is contained in:
@@ -3067,8 +3067,10 @@ package android.animation {
|
||||
|
||||
public static abstract interface Animator.AnimatorListener {
|
||||
method public abstract void onAnimationCancel(android.animation.Animator);
|
||||
method public default void onAnimationEnd(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationEnd(android.animation.Animator);
|
||||
method public abstract void onAnimationRepeat(android.animation.Animator);
|
||||
method public default void onAnimationStart(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationStart(android.animation.Animator);
|
||||
}
|
||||
|
||||
@@ -3104,6 +3106,8 @@ package android.animation {
|
||||
method public void playSequentially(java.util.List<android.animation.Animator>);
|
||||
method public void playTogether(android.animation.Animator...);
|
||||
method public void playTogether(java.util.Collection<android.animation.Animator>);
|
||||
method public void reverse();
|
||||
method public void setCurrentPlayTime(long);
|
||||
method public android.animation.AnimatorSet setDuration(long);
|
||||
method public void setInterpolator(android.animation.TimeInterpolator);
|
||||
method public void setStartDelay(long);
|
||||
|
||||
@@ -3186,8 +3186,10 @@ package android.animation {
|
||||
|
||||
public static abstract interface Animator.AnimatorListener {
|
||||
method public abstract void onAnimationCancel(android.animation.Animator);
|
||||
method public default void onAnimationEnd(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationEnd(android.animation.Animator);
|
||||
method public abstract void onAnimationRepeat(android.animation.Animator);
|
||||
method public default void onAnimationStart(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationStart(android.animation.Animator);
|
||||
}
|
||||
|
||||
@@ -3223,6 +3225,8 @@ package android.animation {
|
||||
method public void playSequentially(java.util.List<android.animation.Animator>);
|
||||
method public void playTogether(android.animation.Animator...);
|
||||
method public void playTogether(java.util.Collection<android.animation.Animator>);
|
||||
method public void reverse();
|
||||
method public void setCurrentPlayTime(long);
|
||||
method public android.animation.AnimatorSet setDuration(long);
|
||||
method public void setInterpolator(android.animation.TimeInterpolator);
|
||||
method public void setStartDelay(long);
|
||||
|
||||
@@ -3067,8 +3067,10 @@ package android.animation {
|
||||
|
||||
public static abstract interface Animator.AnimatorListener {
|
||||
method public abstract void onAnimationCancel(android.animation.Animator);
|
||||
method public default void onAnimationEnd(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationEnd(android.animation.Animator);
|
||||
method public abstract void onAnimationRepeat(android.animation.Animator);
|
||||
method public default void onAnimationStart(android.animation.Animator, boolean);
|
||||
method public abstract void onAnimationStart(android.animation.Animator);
|
||||
}
|
||||
|
||||
@@ -3104,6 +3106,8 @@ package android.animation {
|
||||
method public void playSequentially(java.util.List<android.animation.Animator>);
|
||||
method public void playTogether(android.animation.Animator...);
|
||||
method public void playTogether(java.util.Collection<android.animation.Animator>);
|
||||
method public void reverse();
|
||||
method public void setCurrentPlayTime(long);
|
||||
method public android.animation.AnimatorSet setDuration(long);
|
||||
method public void setInterpolator(android.animation.TimeInterpolator);
|
||||
method public void setStartDelay(long);
|
||||
|
||||
@@ -276,8 +276,9 @@ public class AnimationHandler {
|
||||
* Run animation based on the frame time.
|
||||
* @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time
|
||||
* base.
|
||||
* @return if the animation has finished.
|
||||
*/
|
||||
void doAnimationFrame(long frameTime);
|
||||
boolean doAnimationFrame(long frameTime);
|
||||
|
||||
/**
|
||||
* This notifies the callback of frame commit time. Frame commit time is the time after
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.ArrayList;
|
||||
* This is the superclass for classes which provide basic support for animations which can be
|
||||
* started, ended, and have <code>AnimatorListeners</code> added to them.
|
||||
*/
|
||||
public abstract class Animator implements Cloneable {
|
||||
public abstract class Animator implements Cloneable, AnimationHandler.AnimationFrameCallback {
|
||||
|
||||
/**
|
||||
* The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
|
||||
@@ -464,12 +464,103 @@ public abstract class Animator implements Cloneable {
|
||||
throw new IllegalStateException("Reverse is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public boolean doAnimationFrame(long frameTime) {
|
||||
// TODO: Need to find a better signal than this
|
||||
return getDuration() + getStartDelay() >= frameTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void commitAnimationFrame(long frameTime) {}
|
||||
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
* This call starts the animation in regular or reverse direction without requiring them to
|
||||
* register frame callbacks. The caller will be responsible for all the subsequent animation
|
||||
* pulses. Specifically, the caller needs to call doAnimationFrame(...) for the animation on
|
||||
* every frame.
|
||||
*
|
||||
* @param inReverse whether the animation should play in reverse direction
|
||||
*/
|
||||
void startWithoutPulsing(boolean inReverse) {
|
||||
if (inReverse) {
|
||||
reverse();
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
* Skips the animation value to end/start, depending on whether the play direction is forward
|
||||
* or backward.
|
||||
*
|
||||
* @param inReverse whether the end value is based on a reverse direction. If yes, this is
|
||||
* equivalent to skip to start value in a forward playing direction.
|
||||
*/
|
||||
void skipToEndValue(boolean inReverse) {}
|
||||
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*
|
||||
* Returns whether the animation has start/end values setup. For most of the animations, this
|
||||
* should always be true. For ObjectAnimators, the start values are setup in the initialization
|
||||
* of the animation.
|
||||
*/
|
||||
boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*/
|
||||
void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {}
|
||||
|
||||
/**
|
||||
* <p>An animation listener receives notifications from an animation.
|
||||
* Notifications indicate animation related events, such as the end or the
|
||||
* repetition of the animation.</p>
|
||||
*/
|
||||
public static interface AnimatorListener {
|
||||
|
||||
/**
|
||||
* <p>Notifies the start of the animation as well as the animation's overall play direction.
|
||||
* This method's default behavior is to call {@link #onAnimationStart(Animator)}. This
|
||||
* method can be overridden, though not required, to get the additional play direction info
|
||||
* when an animation starts. Skipping calling super when overriding this method results in
|
||||
* {@link #onAnimationStart(Animator)} not getting called.
|
||||
*
|
||||
* @param animation The started animation.
|
||||
* @param isReverse Whether the animation is playing in reverse.
|
||||
*/
|
||||
default void onAnimationStart(Animator animation, boolean isReverse) {
|
||||
onAnimationStart(animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Notifies the end of the animation. This callback is not invoked
|
||||
* for animations with repeat count set to INFINITE.</p>
|
||||
*
|
||||
* <p>This method's default behavior is to call {@link #onAnimationEnd(Animator)}. This
|
||||
* method can be overridden, though not required, to get the additional play direction info
|
||||
* when an animation ends. Skipping calling super when overriding this method results in
|
||||
* {@link #onAnimationEnd(Animator)} not getting called.
|
||||
*
|
||||
* @param animation The animation which reached its end.
|
||||
* @param isReverse Whether the animation is playing in reverse.
|
||||
*/
|
||||
default void onAnimationEnd(Animator animation, boolean isReverse) {
|
||||
onAnimationEnd(animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Notifies the start of the animation.</p>
|
||||
*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -991,6 +991,11 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isInitialized() {
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectAnimator clone() {
|
||||
final ObjectAnimator anim = (ObjectAnimator) super.clone();
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Trace;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.Log;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
@@ -67,7 +68,7 @@ import java.util.HashMap;
|
||||
* </div>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
|
||||
public class ValueAnimator extends Animator {
|
||||
private static final String TAG = "ValueAnimator";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@@ -90,7 +91,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
*
|
||||
* Whenever mStartTime is set, you must also update mStartTimeCommitted.
|
||||
*/
|
||||
long mStartTime;
|
||||
long mStartTime = -1;
|
||||
|
||||
/**
|
||||
* When true, the start time has been firmly committed as a chosen reference point in
|
||||
@@ -152,7 +153,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
/**
|
||||
* Tracks the time (in milliseconds) when the last frame arrived.
|
||||
*/
|
||||
private long mLastFrameTime = 0;
|
||||
private long mLastFrameTime = -1;
|
||||
|
||||
/**
|
||||
* Tracks the time (in milliseconds) when the first frame arrived. Note the frame may arrive
|
||||
* during the start delay.
|
||||
*/
|
||||
private long mFirstFrameTime = -1;
|
||||
|
||||
/**
|
||||
* Additional playing state to indicate whether an animator has been start()'d. There is
|
||||
@@ -211,6 +218,12 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
*/
|
||||
private int mRepeatMode = RESTART;
|
||||
|
||||
/**
|
||||
* Whether or not the animator should register for its own animation callback to receive
|
||||
* animation pulse.
|
||||
*/
|
||||
private boolean mSelfPulse = true;
|
||||
|
||||
/**
|
||||
* The time interpolator to be used. The elapsed fraction of the animation will be passed
|
||||
* through this interpolator to calculate the interpolated fraction, which is then used to
|
||||
@@ -628,7 +641,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
mSeekFraction = fraction;
|
||||
}
|
||||
mOverallFraction = fraction;
|
||||
final float currentIterationFraction = getCurrentIterationFraction(fraction);
|
||||
final float currentIterationFraction = getCurrentIterationFraction(fraction, mReversing);
|
||||
animateValue(currentIterationFraction);
|
||||
}
|
||||
|
||||
@@ -654,11 +667,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
* should be played backwards. E.g. When the animation is played backwards in an iteration,
|
||||
* the fraction for that iteration will go from 1f to 0f.
|
||||
*/
|
||||
private float getCurrentIterationFraction(float fraction) {
|
||||
private float getCurrentIterationFraction(float fraction, boolean inReverse) {
|
||||
fraction = clampFraction(fraction);
|
||||
int iteration = getCurrentIteration(fraction);
|
||||
float currentFraction = fraction - iteration;
|
||||
return shouldPlayBackward(iteration) ? 1f - currentFraction : currentFraction;
|
||||
return shouldPlayBackward(iteration, inReverse) ? 1f - currentFraction : currentFraction;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -682,18 +695,18 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
* whether the entire animation is being reversed, 2) repeat mode applied to the current
|
||||
* iteration.
|
||||
*/
|
||||
private boolean shouldPlayBackward(int iteration) {
|
||||
private boolean shouldPlayBackward(int iteration, boolean inReverse) {
|
||||
if (iteration > 0 && mRepeatMode == REVERSE &&
|
||||
(iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
|
||||
// if we were seeked to some other iteration in a reversing animator,
|
||||
// figure out the correct direction to start playing based on the iteration
|
||||
if (mReversing) {
|
||||
if (inReverse) {
|
||||
return (iteration % 2) == 0;
|
||||
} else {
|
||||
return (iteration % 2) != 0;
|
||||
}
|
||||
} else {
|
||||
return mReversing;
|
||||
return inReverse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,7 +978,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
(ArrayList<AnimatorListener>) mListeners.clone();
|
||||
int numListeners = tmpListeners.size();
|
||||
for (int i = 0; i < numListeners; ++i) {
|
||||
tmpListeners.get(i).onAnimationStart(this);
|
||||
tmpListeners.get(i).onAnimationStart(this, mReversing);
|
||||
}
|
||||
}
|
||||
mStartListenersCalled = true;
|
||||
@@ -984,11 +997,12 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
*
|
||||
* @param playBackwards Whether the ValueAnimator should start playing in reverse.
|
||||
*/
|
||||
private void start(boolean playBackwards) {
|
||||
private void start(boolean playBackwards, boolean selfPulse) {
|
||||
if (Looper.myLooper() == null) {
|
||||
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
|
||||
}
|
||||
mReversing = playBackwards;
|
||||
mSelfPulse = selfPulse;
|
||||
// Special case: reversing from seek-to-0 should act as if not seeked at all.
|
||||
if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
|
||||
if (mRepeatCount == INFINITE) {
|
||||
@@ -1006,11 +1020,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
// Resets mLastFrameTime when start() is called, so that if the animation was running,
|
||||
// calling start() would put the animation in the
|
||||
// started-but-not-yet-reached-the-first-frame phase.
|
||||
mLastFrameTime = 0;
|
||||
AnimationHandler animationHandler = AnimationHandler.getInstance();
|
||||
animationHandler.addAnimationFrameCallback(this, (long) (mStartDelay * sDurationScale));
|
||||
mLastFrameTime = -1;
|
||||
mFirstFrameTime = -1;
|
||||
addAnimationCallback((long) (mStartDelay * sDurationScale));
|
||||
|
||||
if (mStartDelay == 0 || mSeekFraction >= 0) {
|
||||
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
|
||||
// If there's no start delay, init the animation and notify start listeners right away
|
||||
// to be consistent with the previous behavior. Otherwise, postpone this until the first
|
||||
// frame after the start delay.
|
||||
@@ -1026,9 +1040,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
}
|
||||
}
|
||||
|
||||
void startWithoutPulsing(boolean inReverse) {
|
||||
start(inReverse, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
start(false);
|
||||
start(false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1073,7 +1091,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
} else if (!mInitialized) {
|
||||
initAnimation();
|
||||
}
|
||||
animateValue(shouldPlayBackward(mRepeatCount) ? 0f : 1f);
|
||||
animateValue(shouldPlayBackward(mRepeatCount, mReversing) ? 0f : 1f);
|
||||
endAnimation();
|
||||
}
|
||||
|
||||
@@ -1086,8 +1104,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
if (mPaused && !mResumed) {
|
||||
mResumed = true;
|
||||
if (mPauseTime > 0) {
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.addAnimationFrameCallback(this, 0);
|
||||
addAnimationCallback(0);
|
||||
}
|
||||
}
|
||||
super.resume();
|
||||
@@ -1133,7 +1150,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
mReversing = !mReversing;
|
||||
end();
|
||||
} else {
|
||||
start(true);
|
||||
start(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1153,8 +1170,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
if (mAnimationEndRequested) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.removeCallback(this);
|
||||
removeAnimationCallback();
|
||||
|
||||
mAnimationEndRequested = true;
|
||||
mPaused = false;
|
||||
@@ -1166,16 +1182,18 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
mRunning = false;
|
||||
mStarted = false;
|
||||
mStartListenersCalled = false;
|
||||
mLastFrameTime = -1;
|
||||
mFirstFrameTime = -1;
|
||||
mReversing = false;
|
||||
mLastFrameTime = 0;
|
||||
if (notify && mListeners != null) {
|
||||
ArrayList<AnimatorListener> tmpListeners =
|
||||
(ArrayList<AnimatorListener>) mListeners.clone();
|
||||
int numListeners = tmpListeners.size();
|
||||
for (int i = 0; i < numListeners; ++i) {
|
||||
tmpListeners.get(i).onAnimationEnd(this);
|
||||
tmpListeners.get(i).onAnimationEnd(this, mReversing);
|
||||
}
|
||||
}
|
||||
mReversing = false;
|
||||
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
|
||||
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
|
||||
System.identityHashCode(this));
|
||||
@@ -1211,7 +1229,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
* is called (or after start delay if any), which may be before the animation loop starts.
|
||||
*/
|
||||
private boolean isPulsingInternal() {
|
||||
return mLastFrameTime > 0;
|
||||
return mLastFrameTime >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1276,12 +1294,76 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
done = true;
|
||||
}
|
||||
mOverallFraction = clampFraction(fraction);
|
||||
float currentIterationFraction = getCurrentIterationFraction(mOverallFraction);
|
||||
float currentIterationFraction = getCurrentIterationFraction(
|
||||
mOverallFraction, mReversing);
|
||||
animateValue(currentIterationFraction);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*
|
||||
* This method does not modify any fields of the animation. It should be called when seeking
|
||||
* in an AnimatorSet. When the last play time and current play time are of different repeat
|
||||
* iterations,
|
||||
* {@link android.view.animation.Animation.AnimationListener#onAnimationRepeat(Animation)}
|
||||
* will be called.
|
||||
*/
|
||||
@Override
|
||||
void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
|
||||
if (currentPlayTime < 0 || lastPlayTime < 0) {
|
||||
throw new UnsupportedOperationException("Error: Play time should never be negative.");
|
||||
}
|
||||
|
||||
initAnimation();
|
||||
// Check whether repeat callback is needed only when repeat count is non-zero
|
||||
if (mRepeatCount > 0) {
|
||||
int iteration = (int) (currentPlayTime / mDuration);
|
||||
int lastIteration = (int) (lastPlayTime / mDuration);
|
||||
|
||||
// Clamp iteration to [0, mRepeatCount]
|
||||
iteration = Math.min(iteration, mRepeatCount);
|
||||
lastIteration = Math.min(lastIteration, mRepeatCount);
|
||||
|
||||
if (iteration != lastIteration) {
|
||||
if (mListeners != null) {
|
||||
int numListeners = mListeners.size();
|
||||
for (int i = 0; i < numListeners; ++i) {
|
||||
mListeners.get(i).onAnimationRepeat(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mRepeatCount != INFINITE && currentPlayTime >= (mRepeatCount + 1) * mDuration) {
|
||||
skipToEndValue(inReverse);
|
||||
} else {
|
||||
// Find the current fraction:
|
||||
float fraction = currentPlayTime / (float) mDuration;
|
||||
fraction = getCurrentIterationFraction(fraction, inReverse);
|
||||
animateValue(fraction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
* Skips the animation value to end/start, depending on whether the play direction is forward
|
||||
* or backward.
|
||||
*
|
||||
* @param inReverse whether the end value is based on a reverse direction. If yes, this is
|
||||
* equivalent to skip to start value in a forward playing direction.
|
||||
*/
|
||||
void skipToEndValue(boolean inReverse) {
|
||||
initAnimation();
|
||||
float endFraction = inReverse ? 0f : 1f;
|
||||
if (mRepeatCount % 2 == 1 && mRepeatMode == REVERSE) {
|
||||
// This would end on fraction = 0
|
||||
endFraction = 0f;
|
||||
}
|
||||
animateValue(endFraction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a frame of the animation, adjusting the start time if needed.
|
||||
*
|
||||
@@ -1289,11 +1371,39 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
* @return true if the animation has ended.
|
||||
* @hide
|
||||
*/
|
||||
public final void doAnimationFrame(long frameTime) {
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
if (mLastFrameTime == 0) {
|
||||
public final boolean doAnimationFrame(long frameTime) {
|
||||
if (!mRunning && mStartTime < 0) {
|
||||
// First frame during delay
|
||||
mStartTime = frameTime + mStartDelay;
|
||||
}
|
||||
|
||||
// Handle pause/resume
|
||||
if (mPaused) {
|
||||
mPauseTime = frameTime;
|
||||
removeAnimationCallback();
|
||||
return false;
|
||||
} else if (mResumed) {
|
||||
mResumed = false;
|
||||
if (mPauseTime > 0) {
|
||||
// Offset by the duration that the animation was paused
|
||||
mStartTime += (frameTime - mPauseTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mRunning) {
|
||||
// If not running, that means the animation is in the start delay phase. In the case of
|
||||
// reversing, we want to run start delay in the end.
|
||||
if (mStartTime > frameTime) {
|
||||
// During start delay
|
||||
return false;
|
||||
} else {
|
||||
// Start delay has passed.
|
||||
mRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mLastFrameTime < 0) {
|
||||
// First frame
|
||||
handler.addOneShotCommitCallback(this);
|
||||
if (mStartDelay > 0) {
|
||||
startAnimation();
|
||||
}
|
||||
@@ -1307,19 +1417,6 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
mStartTimeCommitted = false; // allow start time to be compensated for jank
|
||||
}
|
||||
mLastFrameTime = frameTime;
|
||||
if (mPaused) {
|
||||
mPauseTime = frameTime;
|
||||
handler.removeCallback(this);
|
||||
return;
|
||||
} else if (mResumed) {
|
||||
mResumed = false;
|
||||
if (mPauseTime > 0) {
|
||||
// Offset by the duration that the animation was paused
|
||||
mStartTime += (frameTime - mPauseTime);
|
||||
mStartTimeCommitted = false; // allow start time to be compensated for jank
|
||||
}
|
||||
handler.addOneShotCommitCallback(this);
|
||||
}
|
||||
// The frame time might be before the start time during the first frame of
|
||||
// an animation. The "current time" must always be on or after the start
|
||||
// time to avoid animating frames at negative time intervals. In practice, this
|
||||
@@ -1330,6 +1427,31 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
if (finished) {
|
||||
endAnimation();
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
private void addOneShotCommitCallback() {
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.addOneShotCommitCallback(this);
|
||||
}
|
||||
|
||||
private void removeAnimationCallback() {
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.removeCallback(this);
|
||||
}
|
||||
|
||||
private void addAnimationCallback(long delay) {
|
||||
if (!mSelfPulse) {
|
||||
return;
|
||||
}
|
||||
AnimationHandler handler = AnimationHandler.getInstance();
|
||||
handler.addAnimationFrameCallback(this, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1384,11 +1506,12 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
|
||||
anim.mPaused = false;
|
||||
anim.mResumed = false;
|
||||
anim.mStartListenersCalled = false;
|
||||
anim.mStartTime = 0;
|
||||
anim.mStartTime = -1;
|
||||
anim.mStartTimeCommitted = false;
|
||||
anim.mAnimationEndRequested = false;
|
||||
anim.mPauseTime = 0;
|
||||
anim.mLastFrameTime = 0;
|
||||
anim.mPauseTime = -1;
|
||||
anim.mLastFrameTime = -1;
|
||||
anim.mFirstFrameTime = -1;
|
||||
anim.mOverallFraction = 0;
|
||||
anim.mCurrentFraction = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user