Merge "Improved notification scroller animation logic"

This commit is contained in:
Selim Cinek
2014-05-07 15:42:41 +00:00
committed by Android (Google) Code Review
2 changed files with 102 additions and 90 deletions

View File

@@ -695,7 +695,7 @@ public class NotificationStackScrollLayout extends ViewGroup
// mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());
// }
}
requestChildrenUpdate();
updateChildren();
}
// Keep on drawing until the animation has finished.
@@ -705,7 +705,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private void customScrollTo(int y) {
mOwnScrollY = y;
requestChildrenUpdate();
updateChildren();
}
@Override
@@ -721,7 +721,7 @@ public class NotificationStackScrollLayout extends ViewGroup
if (clampedY) {
mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange());
}
requestChildrenUpdate();
updateChildren();
} else {
customScrollTo(scrollY);
scrollTo(scrollX, mScrollY);

View File

@@ -132,10 +132,10 @@ public class StackStateAnimator {
ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_HEIGHT);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
if (previousAnimator == null) {
// no animation was running, but also no new animation should be performed,
// lets just apply the value
child.setActualHeight(viewState.height);
// no new animation needed, let's just apply the value
child.setActualHeight(viewState.height);
if (previousAnimator != null && !isRunning()) {
onAnimationFinished();
}
return;
}
@@ -158,7 +158,7 @@ public class StackStateAnimator {
child.setTag(TAG_END_HEIGHT, null);
}
});
animator.start();
startInstantly(animator);
child.setTag(TAG_ANIMATOR_HEIGHT, animator);
child.setTag(TAG_END_HEIGHT, viewState.height);
}
@@ -173,13 +173,13 @@ public class StackStateAnimator {
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_ALPHA);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
if (previousAnimator == null) {
// no animation was running, but also no new animation should be performed,
// lets just apply the value
child.setAlpha(endAlpha);
if (endAlpha == 0) {
child.setVisibility(View.INVISIBLE);
}
// no new animation needed, let's just apply the value
child.setAlpha(endAlpha);
if (endAlpha == 0) {
child.setVisibility(View.INVISIBLE);
}
if (previousAnimator != null && !isRunning()) {
onAnimationFinished();
}
return;
}
@@ -213,6 +213,7 @@ public class StackStateAnimator {
mWasCancelled = false;
}
});
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@@ -221,11 +222,90 @@ public class StackStateAnimator {
}
});
animator.start();
startInstantly(animator);
child.setTag(TAG_ANIMATOR_ALPHA, animator);
child.setTag(TAG_END_ALPHA, endAlpha);
}
private void startZTranslationAnimation(final ExpandableView child,
final StackScrollState.ViewState viewState, boolean hasNewEvents) {
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
if (previousEndValue != null && previousEndValue == viewState.zTranslation) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Z);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
// no new animation needed, let's just apply the value
child.setTranslationZ(viewState.zTranslation);
if (previousAnimator != null && !isRunning()) {
onAnimationFinished();
}
return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Z,
child.getTranslationZ(), viewState.zTranslation);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, null);
child.setTag(TAG_END_TRANSLATION_Z, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
child.setTag(TAG_END_TRANSLATION_Z, viewState.zTranslation);
}
private void startYTranslationAnimation(final ExpandableView child,
StackScrollState.ViewState viewState, boolean hasNewEvents) {
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
if (previousEndValue != null && previousEndValue == viewState.yTranslation) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
// no new animation needed, let's just apply the value
child.setTranslationY(viewState.yTranslation);
if (previousAnimator != null && !isRunning()) {
onAnimationFinished();
}
return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y,
child.getTranslationY(), viewState.yTranslation);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.setDuration(newDuration);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
}
});
startInstantly(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
child.setTag(TAG_END_TRANSLATION_Y, viewState.yTranslation);
}
/**
* Start an animator instantly instead of waiting on the next synchronization frame
*/
private void startInstantly(ValueAnimator animator) {
animator.start();
animator.setCurrentPlayTime(0);
}
/**
* @return an adapter which ensures that onAnimationFinished is called once no animation is
* running anymore
@@ -259,75 +339,6 @@ public class StackStateAnimator {
mWasCancelled = false;
}
};
}
private void startZTranslationAnimation(final ExpandableView child,
final StackScrollState.ViewState viewState, boolean hasNewEvents) {
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
if (previousEndValue != null && previousEndValue == viewState.zTranslation) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Z);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
if (previousAnimator == null) {
// no animation was running, but also no new animation should be performed,
// lets just apply the value
child.setTranslationZ(viewState.zTranslation);
}
return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Z,
child.getTranslationZ(), viewState.zTranslation);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, null);
child.setTag(TAG_END_TRANSLATION_Z, null);
}
});
animator.start();
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
child.setTag(TAG_END_TRANSLATION_Z, viewState.zTranslation);
}
private void startYTranslationAnimation(final ExpandableView child,
StackScrollState.ViewState viewState, boolean hasNewEvents) {
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
if (previousEndValue != null && previousEndValue == viewState.yTranslation) {
return;
}
ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator, hasNewEvents);
if (newDuration <= 0) {
if (previousAnimator == null) {
// no animation was running, but also no new animation should be performed,
// lets just apply the value
child.setTranslationY(viewState.yTranslation);
}
return;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y,
child.getTranslationY(), viewState.yTranslation);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
}
});
animator.start();
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
child.setTag(TAG_END_TRANSLATION_Y, viewState.yTranslation);
}
private <T> T getChildTag(View child, int tag) {
@@ -343,18 +354,19 @@ public class StackStateAnimator {
*/
private long cancelAnimatorAndGetNewDuration(ValueAnimator previousAnimator,
boolean hasNewEvents) {
long newDuration = ANIMATION_DURATION;
if (previousAnimator != null) {
previousAnimator.cancel();
if (!hasNewEvents) {
// This is only an update, no new event came in. lets just take the remaining
// duration as the new duration
return (long) ((1.0f - previousAnimator.getAnimatedFraction()) *
previousAnimator.getDuration());
newDuration = previousAnimator.getDuration()
- previousAnimator.getCurrentPlayTime();
}
previousAnimator.cancel();
} else if (!hasNewEvents){
return 0;
newDuration = 0;
}
return ANIMATION_DURATION;
return newDuration;
}
private void onAnimationFinished() {