diff options
2 files changed, 42 insertions, 16 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index 433e5c77e128..ab62ed65716e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -470,15 +470,8 @@ public class StackStateAnimator { mHeadsUpAppearChildren.add(changingView); mTmpState.copyFrom(changingView.getViewState()); - if (event.headsUpFromBottom) { - // start from the bottom of the screen - mTmpState.setYTranslation( - mHeadsUpAppearHeightBottom + mHeadsUpAppearStartAboveScreen); - } else { - // start from the top of the screen - mTmpState.setYTranslation( - -mStackTopMargin - mHeadsUpAppearStartAboveScreen); - } + // translate the HUN in from the top, or the bottom of the screen + mTmpState.setYTranslation(getHeadsUpYTranslationStart(event.headsUpFromBottom)); // set the height and the initial position mTmpState.applyToView(changingView); mAnimationProperties.setCustomInterpolator(View.TRANSLATION_Y, @@ -522,12 +515,20 @@ public class StackStateAnimator { || event.animationType == ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) { mHeadsUpDisappearChildren.add(changingView); Runnable endRunnable = null; + mTmpState.copyFrom(changingView.getViewState()); if (changingView.getParent() == null) { // This notification was actually removed, so we need to add it // transiently mHostLayout.addTransientView(changingView, 0); changingView.setTransientContainer(mHostLayout); - mTmpState.initFrom(changingView); + if (NotificationsImprovedHunAnimation.isEnabled()) { + // StackScrollAlgorithm cannot find this view because it has been removed + // from the NSSL. To correctly translate the view to the top or bottom of + // the screen (where it animated from), we need to update its translation. + mTmpState.setYTranslation( + getHeadsUpYTranslationStart(event.headsUpFromBottom) + ); + } endRunnable = changingView::removeFromTransientContainer; } @@ -575,16 +576,19 @@ public class StackStateAnimator { changingView.setInRemovalAnimation(true); }; } - if (NotificationsImprovedHunAnimation.isEnabled()) { - mAnimationProperties.setCustomInterpolator(View.TRANSLATION_Y, - Interpolators.FAST_OUT_SLOW_IN_REVERSE); - } long removeAnimationDelay = changingView.performRemoveAnimation( ANIMATION_DURATION_HEADS_UP_DISAPPEAR, 0, 0.0f, true /* isHeadsUpAppear */, startAnimation, postAnimation, getGlobalAnimationFinishedListener()); mAnimationProperties.delay += removeAnimationDelay; + if (NotificationsImprovedHunAnimation.isEnabled()) { + mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR; + mAnimationProperties.setCustomInterpolator(View.TRANSLATION_Y, + Interpolators.FAST_OUT_SLOW_IN_REVERSE); + mAnimationProperties.getAnimationFilter().animateY = true; + mTmpState.animateTo(changingView, mAnimationProperties); + } } else if (endRunnable != null) { endRunnable.run(); } @@ -595,6 +599,15 @@ public class StackStateAnimator { return needsCustomAnimation; } + private float getHeadsUpYTranslationStart(boolean headsUpFromBottom) { + if (headsUpFromBottom) { + // start from the bottom of the screen + return mHeadsUpAppearHeightBottom + mHeadsUpAppearStartAboveScreen; + } + // start from the top of the screen + return -mStackTopMargin - mHeadsUpAppearStartAboveScreen; + } + public void animateOverScrollToAmount(float targetAmount, final boolean onTop, final boolean isRubberbanded) { final float startOverScrollAmount = mHostLayout.getCurrentOverScrollAmount(onTop); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt index 414d3181c282..4f0f91a7ee56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt @@ -18,8 +18,10 @@ package com.android.systemui.statusbar.notification.stack import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.AnimatorTestRule import com.android.systemui.res.R import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation @@ -31,10 +33,12 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mockito.any +import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.description import org.mockito.Mockito.eq import org.mockito.Mockito.verify @@ -45,8 +49,11 @@ private const val HEADS_UP_ABOVE_SCREEN = 80 @SmallTest @RunWith(AndroidTestingRunner::class) +@RunWithLooper class StackStateAnimatorTest : SysuiTestCase() { + @get:Rule val animatorTestRule = AnimatorTestRule(this) + private lateinit var stackStateAnimator: StackStateAnimator private val stackScroller: NotificationStackScrollLayout = mock() private val view: ExpandableView = mock() @@ -112,13 +119,16 @@ class StackStateAnimatorTest : SysuiTestCase() { } @Test + @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME) fun startAnimationForEvents_startsHeadsUpDisappearAnim() { + val disappearDuration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR.toLong() val event = AnimationEvent(view, AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) + clearInvocations(view) stackStateAnimator.startAnimationForEvents(arrayListOf(event), 0) verify(view) .performRemoveAnimation( - /* duration= */ eq(ANIMATION_DURATION_HEADS_UP_DISAPPEAR.toLong()), + /* duration= */ eq(disappearDuration), /* delay= */ eq(0L), /* translationDirection= */ eq(0f), /* isHeadsUpAnimation= */ eq(true), @@ -127,9 +137,12 @@ class StackStateAnimatorTest : SysuiTestCase() { /* animationListener= */ any() ) + animatorTestRule.advanceTimeBy(disappearDuration) // move to the end of SSA animations runnableCaptor.value.run() // execute the end runnable - verify(view, description("should be called at the end of the animation")) + verify(view, description("should be translated to the heads up appear start")) + .translationY = -stackStateAnimator.mHeadsUpAppearStartAboveScreen + verify(view, description("should be called at the end of the disappear animation")) .removeFromTransientContainer() } |