diff options
| author | 2023-06-12 15:38:44 +0000 | |
|---|---|---|
| committer | 2023-06-12 15:38:44 +0000 | |
| commit | 2803d28eb1ca42afc652ba78ad5b1ef0bc3f067f (patch) | |
| tree | ccd841ababf0c2ff6ef339606c554e6bb0770cd7 | |
| parent | 9d2d6d1f223c4d0a4508bbd662e03a2b24fae14e (diff) | |
| parent | ce56e3ff5513669c4caf83266ad2e72b6a900722 (diff) | |
Merge "Fix missing HUN Outro animations" into udc-dev
2 files changed, 110 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 6f1c378f429d..efb7926b8b8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -315,7 +315,8 @@ public class StackScrollAlgorithm { float newNotificationEnd = newYTranslation + newHeight; boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned(); if (mClipNotificationScrollToTop - && ((isHeadsUp && !firstHeadsUp) || child.isHeadsUpAnimatingAway()) + && !firstHeadsUp + && (isHeadsUp || child.isHeadsUpAnimatingAway()) && newNotificationEnd > firstHeadsUpEnd && !ambientState.isShadeExpanded()) { // The bottom of this view is peeking out from under the previous view. @@ -619,13 +620,12 @@ public class StackScrollAlgorithm { updateViewWithShelf(view, viewState, shelfStart); } } - // Avoid pulsing notification flicker during AOD to LS - // A pulsing notification is already expanded, no need to expand it again with animation - if (ambientState.isPulsingRow(view)) { - expansionFraction = 1.0f; + viewState.height = getMaxAllowedChildHeight(view); + if (!view.isPinned() && !view.isHeadsUpAnimatingAway() + && !ambientState.isPulsingRow(view)) { + // The expansion fraction should not affect HUNs or pulsing notifications. + viewState.height *= expansionFraction; } - // Clip height of view right before shelf. - viewState.height = (int) (getMaxAllowedChildHeight(view) * expansionFraction); } algorithmState.mCurrentYPosition += @@ -785,6 +785,8 @@ public class StackScrollAlgorithm { } } if (row.isPinned()) { + // Make sure row yTranslation is at maximum the HUN yTranslation, + // which accounts for AmbientState.stackTopMargin in split-shade. childState.setYTranslation( Math.max(childState.getYTranslation(), headsUpTranslation)); childState.height = Math.max(row.getIntrinsicHeight(), childState.height); @@ -809,7 +811,11 @@ public class StackScrollAlgorithm { } } if (row.isHeadsUpAnimatingAway()) { - childState.setYTranslation(Math.max(childState.getYTranslation(), mHeadsUpInset)); + // Make sure row yTranslation is at maximum the HUN yTranslation, + // which accounts for AmbientState.stackTopMargin in split-shade. + childState.setYTranslation( + Math.max(childState.getYTranslation(), headsUpTranslation)); + // keep it visible for the animation childState.hidden = false; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index e12d179c5aa5..88b1eb3d565c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -35,7 +35,6 @@ import org.mockito.Mockito.`when` as whenever @SmallTest class StackScrollAlgorithmTest : SysuiTestCase() { - @JvmField @Rule var expect: Expect = Expect.create() @@ -82,26 +81,58 @@ class StackScrollAlgorithmTest : SysuiTestCase() { fun resetViewStates_defaultHun_yTranslationIsInset() { whenever(notificationRow.isPinned).thenReturn(true) whenever(notificationRow.isHeadsUp).thenReturn(true) - - stackScrollAlgorithm.resetViewStates(ambientState, 0) - - assertThat(notificationRow.viewState.yTranslation) - .isEqualTo(stackScrollAlgorithm.mHeadsUpInset) + resetViewStates_hunYTranslationIsInset() } @Test - fun resetViewStates_stackMargin_changesHunYTranslation() { + fun resetViewStates_defaultHunWithStackMargin_changesHunYTranslation() { whenever(notificationRow.isPinned).thenReturn(true) whenever(notificationRow.isHeadsUp).thenReturn(true) - val minHeadsUpTranslation = context.resources - .getDimensionPixelSize(R.dimen.notification_side_paddings) + resetViewStates_stackMargin_changesHunYTranslation() + } - // split shade case with top margin introduced by shade's status bar - ambientState.stackTopMargin = 100 - stackScrollAlgorithm.resetViewStates(ambientState, 0) + @Test + fun resetViewStates_hunAnimatingAway_yTranslationIsInset() { + whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true) + resetViewStates_hunYTranslationIsInset() + } - // top margin presence should decrease heads up translation up to minHeadsUpTranslation - assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation) + @Test + fun resetViewStates_hunAnimatingAway_StackMarginChangesHunYTranslation() { + whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true) + resetViewStates_stackMargin_changesHunYTranslation() + } + + @Test + fun resetViewStates_hunAnimatingAway_bottomNotClipped() { + whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true) + + stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) + + assertThat(notificationRow.viewState.clipBottomAmount).isEqualTo(0) + } + + @Test + fun resetViewStates_hunsOverlapping_bottomHunClipped() { + val topHun = mockExpandableNotificationRow() + val bottomHun = mockExpandableNotificationRow() + whenever(topHun.isHeadsUp).thenReturn(true) + whenever(topHun.isPinned).thenReturn(true) + whenever(bottomHun.isHeadsUp).thenReturn(true) + whenever(bottomHun.isPinned).thenReturn(true) + + resetViewStates_hunsOverlapping_bottomHunClipped(topHun, bottomHun) + } + + @Test + fun resetViewStates_hunsOverlappingAndBottomHunAnimatingAway_bottomHunClipped() { + val topHun = mockExpandableNotificationRow() + val bottomHun = mockExpandableNotificationRow() + whenever(topHun.isHeadsUp).thenReturn(true) + whenever(topHun.isPinned).thenReturn(true) + whenever(bottomHun.isHeadsUpAnimatingAway).thenReturn(true) + + resetViewStates_hunsOverlapping_bottomHunClipped(topHun, bottomHun) } @Test @@ -855,6 +886,57 @@ class StackScrollAlgorithmTest : SysuiTestCase() { ambientState.stackHeight = ambientState.stackEndHeight * fraction } + private fun resetViewStates_hunYTranslationIsInset() { + stackScrollAlgorithm.resetViewStates(ambientState, 0) + + assertThat(notificationRow.viewState.yTranslation) + .isEqualTo(stackScrollAlgorithm.mHeadsUpInset) + } + + private fun resetViewStates_stackMargin_changesHunYTranslation() { + val stackTopMargin = 50 + val headsUpTranslationY = stackScrollAlgorithm.mHeadsUpInset - stackTopMargin + + // we need the shelf to mock the real-life behaviour of StackScrollAlgorithm#updateChild + ambientState.shelf = notificationShelf + + // split shade case with top margin introduced by shade's status bar + ambientState.stackTopMargin = stackTopMargin + stackScrollAlgorithm.resetViewStates(ambientState, 0) + + // heads up translation should be decreased by the top margin + assertThat(notificationRow.viewState.yTranslation).isEqualTo(headsUpTranslationY) + } + + private fun resetViewStates_hunsOverlapping_bottomHunClipped( + topHun: ExpandableNotificationRow, + bottomHun: ExpandableNotificationRow + ) { + val topHunHeight = mContext.resources.getDimensionPixelSize( + R.dimen.notification_content_min_height) + val bottomHunHeight = mContext.resources.getDimensionPixelSize( + R.dimen.notification_max_heads_up_height) + whenever(topHun.intrinsicHeight).thenReturn(topHunHeight) + whenever(bottomHun.intrinsicHeight).thenReturn(bottomHunHeight) + + // we need the shelf to mock the real-life behaviour of StackScrollAlgorithm#updateChild + ambientState.shelf = notificationShelf + + // add two overlapping HUNs + hostView.removeAllViews() + hostView.addView(topHun) + hostView.addView(bottomHun) + + stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) + + // the height shouldn't change + assertThat(topHun.viewState.height).isEqualTo(topHunHeight) + assertThat(bottomHun.viewState.height).isEqualTo(bottomHunHeight) + // the HUN at the bottom should be clipped + assertThat(topHun.viewState.clipBottomAmount).isEqualTo(0) + assertThat(bottomHun.viewState.clipBottomAmount).isEqualTo(bottomHunHeight - topHunHeight) + } + private fun resetViewStates_expansionChanging_notificationAlphaUpdated( expansionFraction: Float, expectedAlpha: Float, |