summaryrefslogtreecommitdiffstats
path: root/core/java/android/animation
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2014-12-02 17:51:34 -0800
committerChet Haase <chet@google.com>2014-12-04 15:09:01 -0800
commitf4e3bab9253bba2c0086c35f4e5a1f7e41324876 (patch)
tree3ed907fbd1956ae7aae6052139bdcb01e1aedb0e /core/java/android/animation
parent8d72046b9ba06feadbcf71815a1c6e1017c8da37 (diff)
downloadframeworks_base-f4e3bab9253bba2c0086c35f4e5a1f7e41324876.zip
frameworks_base-f4e3bab9253bba2c0086c35f4e5a1f7e41324876.tar.gz
frameworks_base-f4e3bab9253bba2c0086c35f4e5a1f7e41324876.tar.bz2
Fix seeking behavior
A recent fix to seeking behavior injected a couple of issues that need to be addressed: - the start time should be updated when seeking so that future calculations that depend on it (such as the next animation frame) will use the updated start time based on this seek request. This allows, for example, seeking into a running animator so that that animator will update its current fraction to the new seeked value. - calling reverse() on an unstarted animation would incorrectly set the initial frame of the animation to the end value for one frame before the reverse animation actually began. Issue #18567716 No icons in folders in battery saving mode Issue #18511989 Search bar flashes when icon is picked up and dropped Change-Id: Ie30b7e797468c6ccb3d17d4fb3aba6b9849436b0
Diffstat (limited to 'core/java/android/animation')
-rw-r--r--core/java/android/animation/ValueAnimator.java85
1 files changed, 79 insertions, 6 deletions
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e18aa5c..5a44a74 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -114,6 +114,15 @@ public class ValueAnimator extends Animator {
private boolean mPlayingBackwards = false;
/**
+ * Flag to indicate whether this animator is playing in reverse mode, specifically
+ * by being started or interrupted by a call to reverse(). This flag is different than
+ * mPlayingBackwards, which indicates merely whether the current iteration of the
+ * animator is playing in reverse. It is used in corner cases to determine proper end
+ * behavior.
+ */
+ private boolean mReversing;
+
+ /**
* This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
* repeatCount (if repeatCount!=INFINITE), the animation ends
*/
@@ -545,21 +554,51 @@ public class ValueAnimator extends Animator {
* Sets the position of the animation to the specified fraction. This fraction should
* be between 0 and the total fraction of the animation, including any repetition. That is,
* a fraction of 0 will position the animation at the beginning, a value of 1 at the end,
- * and a value of 2 at the beginning of a reversing animator that repeats once. If
+ * and a value of 2 at the end of a reversing animator that repeats once. If
* the animation has not yet been started, then it will not advance forward after it is
* set to this fraction; it will simply set the fraction to this value and perform any
* appropriate actions based on that fraction. If the animation is already running, then
* setCurrentFraction() will set the current fraction to this value and continue
- * playing from that point.
+ * playing from that point. {@link AnimatorListener} events are not called
+ * due to changing the fraction; those events are only processed while the animation
+ * is running.
*
- * @param fraction The fraction to which the animation is advanced or rewound.
+ * @param fraction The fraction to which the animation is advanced or rewound. Values
+ * outside the range of 0 to the maximum fraction for the animator will be clamped to
+ * the correct range.
*/
public void setCurrentFraction(float fraction) {
initAnimation();
+ if (fraction < 0) {
+ fraction = 0;
+ }
+ int iteration = (int) fraction;
+ if (fraction == 1) {
+ iteration -= 1;
+ } else if (fraction > 1) {
+ if (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE) {
+ if (mRepeatMode == REVERSE) {
+ mPlayingBackwards = (iteration % 2) != 0;
+ }
+ fraction = fraction % 1f;
+ } else {
+ fraction = 1;
+ iteration -= 1;
+ }
+ } else {
+ mPlayingBackwards = mReversing;
+ }
+ mCurrentIteration = iteration;
+ long seekTime = (long) (mDuration * fraction);
+ long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ mStartTime = currentTime - seekTime;
if (mPlayingState != RUNNING) {
mSeekFraction = fraction;
mPlayingState = SEEKED;
}
+ if (mPlayingBackwards) {
+ fraction = 1f - fraction;
+ }
animateValue(fraction);
}
@@ -962,8 +1001,30 @@ public class ValueAnimator extends Animator {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
+ mReversing = playBackwards;
mPlayingBackwards = playBackwards;
- mCurrentIteration = 0;
+ if (playBackwards && mSeekFraction != -1) {
+ if (mSeekFraction == 0 && mCurrentIteration == 0) {
+ // special case: reversing from seek-to-0 should act as if not seeked at all
+ mSeekFraction = 0;
+ } else if (mRepeatCount == INFINITE) {
+ mSeekFraction = 1 - (mSeekFraction % 1);
+ } else {
+ mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);
+ }
+ mCurrentIteration = (int) mSeekFraction;
+ mSeekFraction = mSeekFraction % 1;
+ }
+ if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&
+ (mCurrentIteration < (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 (playBackwards) {
+ mPlayingBackwards = (mCurrentIteration % 2) == 0;
+ } else {
+ mPlayingBackwards = (mCurrentIteration % 2) != 0;
+ }
+ }
int prevPlayingState = mPlayingState;
mPlayingState = STOPPED;
mStarted = true;
@@ -1071,6 +1132,7 @@ public class ValueAnimator extends Animator {
long currentPlayTime = currentTime - mStartTime;
long timeLeft = mDuration - currentPlayTime;
mStartTime = currentTime - timeLeft;
+ mReversing = !mReversing;
} else if (mStarted) {
end();
} else {
@@ -1113,6 +1175,8 @@ public class ValueAnimator extends Animator {
mStarted = false;
mStartListenersCalled = false;
mPlayingBackwards = false;
+ mReversing = false;
+ mCurrentIteration = 0;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
System.identityHashCode(this));
@@ -1201,8 +1265,16 @@ public class ValueAnimator extends Animator {
case RUNNING:
case SEEKED:
float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
+ if (mDuration == 0 && mRepeatCount != INFINITE) {
+ // Skip to the end
+ mCurrentIteration = mRepeatCount;
+ if (!mReversing) {
+ mPlayingBackwards = false;
+ }
+ }
if (fraction >= 1f) {
- if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
+ if (mCurrentIteration < mRepeatCount ||
+ (mRepeatCount == INFINITE && mDuration != 0)) {
// Time to repeat
if (mListeners != null) {
int numListeners = mListeners.size();
@@ -1213,7 +1285,7 @@ public class ValueAnimator extends Animator {
if (mRepeatMode == REVERSE) {
mPlayingBackwards = !mPlayingBackwards;
}
- mCurrentIteration += (int)fraction;
+ mCurrentIteration += (int) fraction;
fraction = fraction % 1f;
mStartTime += mDuration;
} else {
@@ -1313,6 +1385,7 @@ public class ValueAnimator extends Animator {
}
anim.mSeekFraction = -1;
anim.mPlayingBackwards = false;
+ anim.mReversing = false;
anim.mCurrentIteration = 0;
anim.mInitialized = false;
anim.mPlayingState = STOPPED;