am 29a0390b: Merge "Fix bug where folder open animation gets finished early" into jb-mr2-dev
* commit '29a0390b33d2fb6b1e610d5ab2fd2dc0c199d699': Fix bug where folder open animation gets finished early
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user