Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0be30834 authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge "Improved notification scroller animation logic"

parents 010cfd45 3af00cf1
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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);
+76 −64
Original line number Diff line number Diff line
@@ -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
            // 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
            // 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,47 +222,11 @@ public class StackStateAnimator {

            }
        });
        animator.start();
        startInstantly(animator);
        child.setTag(TAG_ANIMATOR_ALPHA, animator);
        child.setTag(TAG_END_ALPHA, endAlpha);
    }

    /**
     * @return an adapter which ensures that onAnimationFinished is called once no animation is
     *         running anymore
     */
    private AnimatorListenerAdapter getGlobalAnimationFinishedListener() {
        if (!mAnimationListenerPool.empty()) {
            return mAnimationListenerPool.pop();
        }

        // We need to create a new one, no reusable ones found
        return new AnimatorListenerAdapter() {
            private boolean mWasCancelled;

            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimatorSet.remove(animation);
                if (mAnimatorSet.isEmpty() && !mWasCancelled) {
                    onAnimationFinished();
                }
                mAnimationListenerPool.push(this);
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                mWasCancelled = true;
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mAnimatorSet.add(animation);
                mWasCancelled = false;
            }
        };

    }

    private void startZTranslationAnimation(final ExpandableView child,
            final StackScrollState.ViewState viewState, boolean hasNewEvents) {
        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
@@ -271,10 +236,11 @@ public class StackStateAnimator {
        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
            // no new animation needed, let's just apply the value
            child.setTranslationZ(viewState.zTranslation);

            if (previousAnimator != null && !isRunning()) {
                onAnimationFinished();
            }
            return;
        }
@@ -282,6 +248,7 @@ public class StackStateAnimator {
        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() {
@@ -291,7 +258,7 @@ public class StackStateAnimator {
                child.setTag(TAG_END_TRANSLATION_Z, null);
            }
        });
        animator.start();
        startInstantly(animator);
        child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
        child.setTag(TAG_END_TRANSLATION_Z, viewState.zTranslation);
    }
@@ -305,10 +272,10 @@ public class StackStateAnimator {
        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
            // no new animation needed, let's just apply the value
            child.setTranslationY(viewState.yTranslation);
            if (previousAnimator != null && !isRunning()) {
                onAnimationFinished();
            }
            return;
        }
@@ -316,6 +283,7 @@ public class StackStateAnimator {
        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() {
@@ -325,11 +293,54 @@ public class StackStateAnimator {
                child.setTag(TAG_END_TRANSLATION_Y, null);
            }
        });
        animator.start();
        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
     */
    private AnimatorListenerAdapter getGlobalAnimationFinishedListener() {
        if (!mAnimationListenerPool.empty()) {
            return mAnimationListenerPool.pop();
        }

        // We need to create a new one, no reusable ones found
        return new AnimatorListenerAdapter() {
            private boolean mWasCancelled;

            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimatorSet.remove(animation);
                if (mAnimatorSet.isEmpty() && !mWasCancelled) {
                    onAnimationFinished();
                }
                mAnimationListenerPool.push(this);
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                mWasCancelled = true;
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mAnimatorSet.add(animation);
                mWasCancelled = false;
            }
        };
    }

    private <T> T getChildTag(View child, int tag) {
        return (T) child.getTag(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() {