summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/launcher2/FirstFrameAnimatorHelper.java52
-rw-r--r--src/com/android/launcher2/LauncherViewPropertyAnimator.java16
2 files changed, 49 insertions, 19 deletions
diff --git a/src/com/android/launcher2/FirstFrameAnimatorHelper.java b/src/com/android/launcher2/FirstFrameAnimatorHelper.java
index 2351dd074..8eac7cd2c 100644
--- a/src/com/android/launcher2/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher2/FirstFrameAnimatorHelper.java
@@ -16,20 +16,24 @@
package com.android.launcher2;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.Animator.AnimatorListener;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.view.View;
+import android.view.ViewPropertyAnimator;
/*
* This is a helper class that listens to updates from the corresponding animation.
* For the first two frames, it adjusts the current play time of the animation to
* prevent jank at the beginning of the animation
*/
-public class FirstFrameAnimatorHelper implements ValueAnimator.AnimatorUpdateListener {
+public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter
+ implements ValueAnimator.AnimatorUpdateListener {
private static final boolean DEBUG = false;
- private static final int MAX_FIRST_FRAME_DELAY = 200;
+ private static final int MAX_DELAY = 1000;
private static final int IDEAL_FRAME_DURATION = 16;
private View mTarget;
private long mStartFrame;
@@ -45,43 +49,65 @@ public class FirstFrameAnimatorHelper implements ValueAnimator.AnimatorUpdateLis
animator.addUpdateListener(this);
}
+ public FirstFrameAnimatorHelper(ViewPropertyAnimator vpa, View target) {
+ mTarget = target;
+ vpa.setListener(this);
+ }
+
+ // only used for ViewPropertyAnimators
+ public void onAnimationStart(Animator animation) {
+ final ValueAnimator va = (ValueAnimator) animation;
+ va.addUpdateListener(FirstFrameAnimatorHelper.this);
+ onAnimationUpdate(va);
+ }
+
public static void initializeDrawListener(View view) {
+ if (sGlobalDrawListener != null) {
+ view.getViewTreeObserver().removeOnDrawListener(sGlobalDrawListener);
+ }
sGlobalDrawListener = new ViewTreeObserver.OnDrawListener() {
private long mTime = System.currentTimeMillis();
public void onDraw() {
sGlobalFrameCounter++;
- long newTime = System.currentTimeMillis();
if (DEBUG) {
+ long newTime = System.currentTimeMillis();
Log.d("FirstFrameAnimatorHelper", "TICK " + (newTime - mTime));
+ mTime = newTime;
}
- mTime = newTime;
}
};
view.getViewTreeObserver().addOnDrawListener(sGlobalDrawListener);
}
public void onAnimationUpdate(final ValueAnimator animation) {
+ final long currentTime = System.currentTimeMillis();
if (mStartTime == -1) {
mStartFrame = sGlobalFrameCounter;
- mStartTime = System.currentTimeMillis();
+ mStartTime = currentTime;
}
- if (!mHandlingOnAnimationUpdate) {
+ if (!mHandlingOnAnimationUpdate &&
+ // If the current play time exceeds the duration, the animation
+ // will get finished, even if we call setCurrentPlayTime -- therefore
+ // don't adjust the animation in that case
+ animation.getCurrentPlayTime() < animation.getDuration()) {
mHandlingOnAnimationUpdate = true;
long frameNum = sGlobalFrameCounter - mStartFrame;
-
// If we haven't drawn our first frame, reset the time to t = 0
- // (give up after 200ms of waiting though - might happen, for example, if we are no
- // longer in the foreground and no frames are being rendered ever)
- if (frameNum == 0 && System.currentTimeMillis() < mStartTime + MAX_FIRST_FRAME_DELAY) {
- mTarget.getRootView().invalidate(); // make sure we'll do a draw
+ // (give up after MAX_DELAY ms of waiting though - might happen, for example, if we
+ // are no longer in the foreground and no frames are being rendered ever)
+ if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY) {
+ // The first frame on animations doesn't always trigger an invalidate...
+ // force an invalidate here to make sure the animation continues to advance
+ mTarget.getRootView().invalidate();
animation.setCurrentPlayTime(0);
// For the second frame, if the first frame took more than 16ms,
// adjust the start time and pretend it took only 16ms anyway. This
// prevents a large jump in the animation due to an expensive first frame
- } else if (frameNum == 1 && !mAdjustedSecondFrameTime &&
- System.currentTimeMillis() > mStartTime + 16) {
+ } else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
+ !mAdjustedSecondFrameTime &&
+ currentTime > mStartTime + IDEAL_FRAME_DURATION) {
animation.setCurrentPlayTime(IDEAL_FRAME_DURATION);
mAdjustedSecondFrameTime = true;
} else {
diff --git a/src/com/android/launcher2/LauncherViewPropertyAnimator.java b/src/com/android/launcher2/LauncherViewPropertyAnimator.java
index 274ff80b3..83b745eb5 100644
--- a/src/com/android/launcher2/LauncherViewPropertyAnimator.java
+++ b/src/com/android/launcher2/LauncherViewPropertyAnimator.java
@@ -53,6 +53,7 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi
TimeInterpolator mInterpolator;
ArrayList<Animator.AnimatorListener> mListeners;
boolean mRunning = false;
+ FirstFrameAnimatorHelper mFirstFrameHelper;
public LauncherViewPropertyAnimator(View target) {
mTarget = target;
@@ -124,12 +125,10 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi
@Override
public void onAnimationStart(Animator animation) {
- // This is the first time we get a handle to the internal ValueAnimator
- // used by the ViewPropertyAnimator.
- // FirstFrameAnimatorHelper hooks itself up to the updates on the animator,
- // and then adjusts the play time to keep the first two frames jank-free
- new FirstFrameAnimatorHelper((ValueAnimator) animation, mTarget)
- .onAnimationUpdate((ValueAnimator) animation);
+ // This is the first time we get a handle to the internal ValueAnimator
+ // used by the ViewPropertyAnimator.
+ mFirstFrameHelper.onAnimationStart(animation);
+
for (int i = 0; i < mListeners.size(); i++) {
Animator.AnimatorListener listener = mListeners.get(i);
listener.onAnimationStart(this);
@@ -193,6 +192,11 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi
@Override
public void start() {
mViewPropertyAnimator = mTarget.animate();
+
+ // FirstFrameAnimatorHelper hooks itself up to the updates on the animator,
+ // and then adjusts the play time to keep the first two frames jank-free
+ mFirstFrameHelper = new FirstFrameAnimatorHelper(mViewPropertyAnimator, mTarget);
+
if (mPropertiesToSet.contains(Properties.TRANSLATION_X)) {
mViewPropertyAnimator.translationX(mTranslationX);
}