Merge "Make sure start() is called for custom animators"

This commit is contained in:
Doris Liu
2017-02-01 04:33:25 +00:00
committed by Android (Google) Code Review
3 changed files with 67 additions and 26 deletions

View File

@@ -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, AnimationHandler.AnimationFrameCallback {
public abstract class Animator implements Cloneable {
/**
* The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
@@ -464,23 +464,13 @@ public abstract class Animator implements Cloneable, AnimationHandler.AnimationF
throw new IllegalStateException("Reverse is not supported");
}
/**
* @hide
*/
@Override
public boolean doAnimationFrame(long frameTime) {
// Pulse an animation frame into the animation.
boolean pulseAnimationFrame(long frameTime) {
// TODO: Need to find a better signal than this. There's a bug in SystemUI that's preventing
// returning !isStarted() from working.
return false;
}
/**
* @hide
*/
@Override
public void commitAnimationFrame(long frameTime) {}
/**
* Internal use only.
* This call starts the animation in regular or reverse direction without requiring them to

View File

@@ -948,7 +948,8 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
for (int i = 0; i < mPlayingSet.size(); i++) {
Node node = mPlayingSet.get(i);
if (!node.mEnded) {
node.mEnded = node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
node.mEnded = node.mAnimation.pulseAnimationFrame(
getPlayTimeForNode(playTime, node));
}
}
@@ -977,6 +978,19 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
return false;
}
/**
* @hide
*/
@Override
public void commitAnimationFrame(long frameTime) {
// No op.
}
@Override
boolean pulseAnimationFrame(long frameTime) {
return doAnimationFrame(frameTime);
}
/**
* When playing forward, we call start() at the animation's scheduled start time, and make sure
* to pump a frame at the animation's scheduled end time.
@@ -993,11 +1007,10 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
if (event.mEvent == AnimationEvent.ANIMATION_END) {
mPlayingSet.add(event.mNode);
node.mAnimation.startWithoutPulsing(true);
node.mAnimation.doAnimationFrame(0);
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED && !node.mEnded) {
// end event:
node.mEnded =
node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
pulseFrame(node, getPlayTimeForNode(playTime, node));
}
}
} else {
@@ -1007,16 +1020,21 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
if (event.mEvent == AnimationEvent.ANIMATION_START) {
mPlayingSet.add(event.mNode);
node.mAnimation.startWithoutPulsing(false);
node.mAnimation.doAnimationFrame(0);
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_END && !node.mEnded) {
// start event:
node.mEnded =
node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
pulseFrame(node, getPlayTimeForNode(playTime, node));
}
}
}
}
private void pulseFrame(Node node, long frameTime) {
if (!node.mEnded) {
node.mEnded = node.mAnimation.pulseAnimationFrame(frameTime);
}
}
private long getPlayTimeForNode(long overallPlayTime, Node node) {
return getPlayTimeForNode(overallPlayTime, node, mReversing);
}

View File

@@ -68,7 +68,7 @@ import java.util.HashMap;
* </div>
*/
@SuppressWarnings("unchecked")
public class ValueAnimator extends Animator {
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
private static final String TAG = "ValueAnimator";
private static final boolean DEBUG = false;
@@ -224,6 +224,12 @@ public class ValueAnimator extends Animator {
*/
private boolean mSelfPulse = true;
/**
* Whether or not the animator has been requested to start without pulsing. This flag gets set
* in startWithoutPulsing(), and reset in start().
*/
private boolean mSuppressSelfPulseRequested = false;
/**
* 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
@@ -997,12 +1003,12 @@ public class ValueAnimator extends Animator {
*
* @param playBackwards Whether the ValueAnimator should start playing in reverse.
*/
private void start(boolean playBackwards, boolean selfPulse) {
private void start(boolean playBackwards) {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
mReversing = playBackwards;
mSelfPulse = selfPulse;
mSelfPulse = !mSuppressSelfPulseRequested;
// Special case: reversing from seek-to-0 should act as if not seeked at all.
if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
if (mRepeatCount == INFINITE) {
@@ -1041,12 +1047,18 @@ public class ValueAnimator extends Animator {
}
void startWithoutPulsing(boolean inReverse) {
start(inReverse, false);
mSuppressSelfPulseRequested = true;
if (inReverse) {
reverse();
} else {
start();
}
mSuppressSelfPulseRequested = false;
}
@Override
public void start() {
start(false, true);
start(false);
}
@Override
@@ -1150,7 +1162,7 @@ public class ValueAnimator extends Animator {
mReversing = !mReversing;
end();
} else {
start(true, true);
start(true);
}
}
@@ -1364,6 +1376,11 @@ public class ValueAnimator extends Animator {
animateValue(endFraction);
}
@Override
boolean isInitialized() {
return mInitialized;
}
/**
* Processes a frame of the animation, adjusting the start time if needed.
*
@@ -1430,6 +1447,20 @@ public class ValueAnimator extends Animator {
return finished;
}
@Override
boolean pulseAnimationFrame(long frameTime) {
if (mSelfPulse) {
// Pulse animation frame will *always* be after calling start(). If mSelfPulse isn't
// set to false at this point, that means child animators did not call super's start().
// This can happen when the Animator is just a non-animating wrapper around a real
// functional animation. In this case, we can't really pulse a frame into the animation,
// because the animation cannot necessarily be properly initialized (i.e. no start/end
// values set).
return false;
}
return doAnimationFrame(frameTime);
}
private void addOneShotCommitCallback() {
if (!mSelfPulse) {
return;
@@ -1514,6 +1545,8 @@ public class ValueAnimator extends Animator {
anim.mFirstFrameTime = -1;
anim.mOverallFraction = 0;
anim.mCurrentFraction = 0;
anim.mSelfPulse = true;
anim.mSuppressSelfPulseRequested = false;
PropertyValuesHolder[] oldValues = mValues;
if (oldValues != null) {