[flexiglass] Fix HUN animation and sizing in QS
Bug: 363209671
Test: manually verified HUN appearance in QS scene
Flag: com.android.systemui.scene_container
Change-Id: I3401d4d200c7d357d451664686765cf2cfd74506
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 1b99a96..fe4a65b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -130,8 +130,8 @@
fun SceneScope.HeadsUpNotificationSpace(
stackScrollView: NotificationScrollView,
viewModel: NotificationsPlaceholderViewModel,
+ useHunBounds: () -> Boolean = { true },
modifier: Modifier = Modifier,
- isPeekFromBottom: Boolean = false,
) {
Box(
modifier =
@@ -141,17 +141,25 @@
.notificationHeadsUpHeight(stackScrollView)
.debugBackground(viewModel, DEBUG_HUN_COLOR)
.onGloballyPositioned { coordinates: LayoutCoordinates ->
- val positionInWindow = coordinates.positionInWindow()
- val boundsInWindow = coordinates.boundsInWindow()
- debugLog(viewModel) {
- "HUNS onGloballyPositioned:" +
- " size=${coordinates.size}" +
- " bounds=$boundsInWindow"
+ // This element is sometimes opted out of the shared element system, so there
+ // can be multiple instances of it during a transition. Thus we need to
+ // determine which instance should feed its bounds to NSSL to avoid providing
+ // conflicting values
+ val useBounds = useHunBounds()
+ if (useBounds) {
+ val positionInWindow = coordinates.positionInWindow()
+ val boundsInWindow = coordinates.boundsInWindow()
+ debugLog(viewModel) {
+ "HUNS onGloballyPositioned:" +
+ " size=${coordinates.size}" +
+ " bounds=$boundsInWindow"
+ }
+ // Note: boundsInWindow doesn't scroll off the screen, so use
+ // positionInWindow
+ // for top bound, which can scroll off screen while snoozing
+ stackScrollView.setHeadsUpTop(positionInWindow.y)
+ stackScrollView.setHeadsUpBottom(boundsInWindow.bottom)
}
- // Note: boundsInWindow doesn't scroll off the screen, so use positionInWindow
- // for top bound, which can scroll off screen while snoozing
- stackScrollView.setHeadsUpTop(positionInWindow.y)
- stackScrollView.setHeadsUpBottom(boundsInWindow.bottom)
}
)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index d91958a..0c69dbd 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -416,11 +416,11 @@
HeadsUpNotificationSpace(
stackScrollView = notificationStackScrollView,
viewModel = notificationsPlaceholderViewModel,
+ useHunBounds = { shouldUseQuickSettingsHunBounds(layoutState.transitionState) },
modifier =
Modifier.align(Alignment.BottomCenter)
.navigationBarsPadding()
.padding(horizontal = shadeHorizontalPadding),
- isPeekFromBottom = true,
)
NotificationScrollingStack(
shadeSession = shadeSession,
@@ -446,3 +446,7 @@
)
}
}
+
+private fun shouldUseQuickSettingsHunBounds(state: TransitionState): Boolean {
+ return state is TransitionState.Idle && state.currentScene == Scenes.QuickSettings
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index f64d0ed..58fbf43 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -77,6 +77,10 @@
}
from(Scenes.Lockscreen, to = Scenes.QuickSettings) { lockscreenToQuickSettingsTransition() }
from(Scenes.Lockscreen, to = Scenes.Gone) { lockscreenToGoneTransition() }
+ from(Scenes.QuickSettings, to = Scenes.Shade) {
+ reversed { shadeToQuickSettingsTransition() }
+ sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false)
+ }
from(Scenes.Shade, to = Scenes.QuickSettings) { shadeToQuickSettingsTransition() }
// Overlay transitions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeadsUpManagerPhone.java
index 02a29e2..1c840e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeadsUpManagerPhone.java
@@ -105,7 +105,8 @@
private final HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
private final ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
= new ArraySet<>();
- private boolean mIsExpanded;
+ private boolean mIsShadeOrQsExpanded;
+ private boolean mIsQsExpanded;
private int mStatusBarState;
private AnimationStateHandler mAnimationStateHandler;
@@ -177,6 +178,10 @@
});
javaAdapter.alwaysCollectFlow(shadeInteractor.isAnyExpanded(),
this::onShadeOrQsExpanded);
+ if (SceneContainerFlag.isEnabled()) {
+ javaAdapter.alwaysCollectFlow(shadeInteractor.isQsExpanded(),
+ this::onQsExpanded);
+ }
if (NotificationThrottleHun.isEnabled()) {
mVisualStabilityProvider.addPersistentReorderingBannedListener(
mOnReorderingBannedListener);
@@ -286,14 +291,19 @@
}
private void onShadeOrQsExpanded(Boolean isExpanded) {
- if (isExpanded != mIsExpanded) {
- mIsExpanded = isExpanded;
+ if (isExpanded != mIsShadeOrQsExpanded) {
+ mIsShadeOrQsExpanded = isExpanded;
if (!SceneContainerFlag.isEnabled() && isExpanded) {
mHeadsUpAnimatingAway.setValue(false);
}
}
}
+ private void onQsExpanded(Boolean isQsExpanded) {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
+ if (isQsExpanded != mIsQsExpanded) mIsQsExpanded = isQsExpanded;
+ }
+
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a reasonable state.
@@ -489,7 +499,10 @@
@Override
protected boolean shouldHeadsUpBecomePinned(NotificationEntry entry) {
- boolean pin = mStatusBarState == StatusBarState.SHADE && !mIsExpanded;
+ boolean pin = mStatusBarState == StatusBarState.SHADE && !mIsShadeOrQsExpanded;
+ if (SceneContainerFlag.isEnabled()) {
+ pin |= mIsQsExpanded;
+ }
if (mBypassController.getBypassEnabled()) {
pin |= mStatusBarState == StatusBarState.KEYGUARD;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index e7c67f9..3c6962a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1260,6 +1260,7 @@
@Override
public void setHeadsUpBottom(float headsUpBottom) {
mAmbientState.setHeadsUpBottom(headsUpBottom);
+ mStateAnimator.setHeadsUpAppearHeightBottom(Math.round(headsUpBottom));
}
@Override