From f83464ed0a1c9215f4100fa018061710ed722ef5 Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Tue, 12 Jan 2016 10:28:28 -0800 Subject: [PATCH] Make Animation.cancel() actually work Cancel() has apparently never worked. Calling cancel() results in the startTime being set to Long.MIN_VALUE. In theory, this means that on the next animation frame (getTransformation()), the elapsed time (currentTime - startTime) should result in a large positive number, which is way more than needed to prove that the elapsed fraction is >1 and therefore that the animation has ended. But in practice, anything subtracting MIN_VALUE will result in a large negative number due to Long wraparound, so the end check fails and the animation continues. Forever. Moreover, event fixing the cancel issue results in a repeating animation continuing to repeat, because the logic was never there to determine whether a repeating animation was canceled. This fix addresses both issues, but in a minimal way. The risk in fixing this for real is changing the behavior of cancel in a way that existing apps would not expect. For example, it's weird that cancel causes one more frame to run. And even weirder that it does so with a negative elapsed duration (resulting in an animation fraction of 0). But I wouldn't want to change that behavior for fear that I'd break apps who rely on that weird behavior. Instead, there's a simple check for for the "expired" check and the "repeat?" check that sees whether the startTime has the magic value of MIN_VALUE, which should only happen when an animation has been canceled. If this is the case, it ensures that the animation ends. For real. Issue #24984018 canceled animation runs forever Change-Id: Ia137eb04bd7df3976a4d9cef86fd39a78dc56f39 --- core/java/android/view/animation/Animation.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index e0dbe2f63487f..1536c29bee5b5 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -850,7 +850,7 @@ public abstract class Animation implements Cloneable { normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f; } - final boolean expired = normalizedTime >= 1.0f; + final boolean expired = normalizedTime >= 1.0f || isCanceled(); mMore = !expired; if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f); @@ -875,7 +875,7 @@ public abstract class Animation implements Cloneable { } if (expired) { - if (mRepeatCount == mRepeated) { + if (mRepeatCount == mRepeated || isCanceled()) { if (!mEnded) { mEnded = true; guard.close(); @@ -905,6 +905,10 @@ public abstract class Animation implements Cloneable { return mMore; } + private boolean isCanceled() { + return mStartTime == Long.MIN_VALUE; + } + private void fireAnimationStart() { if (mListener != null) { if (mListenerHandler == null) mListener.onAnimationStart(this);