diff options
9 files changed, 106 insertions, 22 deletions
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 0bef05dc00ba..9e292d06613b 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 @@ -68,7 +68,6 @@ import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInWindow -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp @@ -82,7 +81,6 @@ import com.android.compose.animation.scene.LowestZIndexContentPicker import com.android.compose.animation.scene.NestedScrollBehavior import com.android.compose.animation.scene.SceneScope import com.android.compose.modifiers.thenIf -import com.android.internal.policy.SystemBarUtils import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.res.R @@ -137,14 +135,16 @@ fun SceneScope.HeadsUpNotificationSpace( .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" } - // Note: boundsInWindow doesn't scroll off the screen - stackScrollView.setHeadsUpTop(boundsInWindow.top) + // 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) } ) @@ -159,16 +159,10 @@ fun SceneScope.SnoozeableHeadsUpNotificationSpace( stackScrollView: NotificationScrollView, viewModel: NotificationsPlaceholderViewModel, ) { - val context = LocalContext.current - val density = LocalDensity.current - val statusBarHeight = SystemBarUtils.getStatusBarHeight(context) - val headsUpPadding = - with(density) { dimensionResource(id = R.dimen.heads_up_status_bar_padding).roundToPx() } - val isHeadsUp by viewModel.isHeadsUpOrAnimatingAway.collectAsStateWithLifecycle(false) var scrollOffset by remember { mutableFloatStateOf(0f) } - val minScrollOffset = -(statusBarHeight + headsUpPadding.toFloat()) + val minScrollOffset = -(stackScrollView.getHeadsUpInset().toFloat()) val maxScrollOffset = 0f val scrollableState = rememberScrollableState { delta -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index 7c3072df0875..6a2c60276186 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -139,6 +139,9 @@ public class AmbientState implements Dumpable { /** Fraction of shade expansion. */ private float mExpansionFraction; + /** Fraction of QS expansion. 0 when in shade, 1 when in QS. */ + private float mQsExpansionFraction; + /** Height of the notifications panel when expansion completes. */ private float mStackEndHeight; @@ -208,6 +211,14 @@ public class AmbientState implements Dumpable { } /** + * @param expansionFraction Fraction of QS expansion. + */ + public void setQsExpansionFraction(float expansionFraction) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + mQsExpansionFraction = expansionFraction; + } + + /** * @param isSwipingUp Whether we are swiping up. */ public void setSwipingUp(boolean isSwipingUp) { @@ -258,6 +269,14 @@ public class AmbientState implements Dumpable { } /** + * @return Fraction of QS expansion. + */ + public float getQsExpansionFraction() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return 0f; + return mQsExpansionFraction; + } + + /** * @see #getStackHeight() */ public void setStackHeight(float stackHeight) { @@ -837,6 +856,7 @@ public class AmbientState implements Dumpable { pw.println("mAppearFraction=" + mAppearFraction); pw.println("mAppearing=" + mAppearing); pw.println("mExpansionFraction=" + mExpansionFraction); + pw.println("mQsExpansionFraction=" + mQsExpansionFraction); pw.println("mExpandingVelocity=" + mExpandingVelocity); pw.println("mOverScrollTopAmount=" + mOverScrollTopAmount); pw.println("mOverScrollBottomAmount=" + mOverScrollBottomAmount); 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 07b0b830cf6c..f26f8405e299 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 @@ -1244,6 +1244,7 @@ public class NotificationStackScrollLayout @Override public void setHeadsUpTop(float headsUpTop) { mAmbientState.setHeadsUpTop(headsUpTop); + requestChildrenUpdate(); } @Override @@ -1563,6 +1564,12 @@ public class NotificationStackScrollLayout } } + @Override + public void setQsExpandFraction(float expandFraction) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + mAmbientState.setQsExpansionFraction(expandFraction); + } + /** * Update the height of the panel. * @@ -2534,6 +2541,11 @@ public class NotificationStackScrollLayout return getTopHeadsUpIntrinsicHeight(); } + @Override + public int getHeadsUpInset() { + return mHeadsUpInset; + } + /** * Calculate the gap height between two different views * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index f35d6660edd9..55f05662f0c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -132,6 +132,7 @@ import com.android.systemui.statusbar.notification.stack.ui.viewbinder.Notificat import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpNotificationViewControllerEmptyImpl; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; +import com.android.systemui.statusbar.phone.HeadsUpTouchHelper.HeadsUpNotificationViewController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; @@ -773,7 +774,7 @@ public class NotificationStackScrollLayoutController implements Dumpable { mHeadsUpManager, statusBarService.get(), getHeadsUpCallback(), - new HeadsUpNotificationViewControllerEmptyImpl() + getHeadsUpNotificationViewController() ); } mNotificationRoundnessManager = notificationRoundnessManager; @@ -1851,6 +1852,32 @@ public class NotificationStackScrollLayoutController implements Dumpable { return mTouchHandler; } + private HeadsUpNotificationViewController getHeadsUpNotificationViewController() { + HeadsUpNotificationViewController headsUpViewController; + if (SceneContainerFlag.isEnabled()) { + headsUpViewController = new HeadsUpNotificationViewController() { + @Override + public void setHeadsUpDraggingStartingHeight(int startHeight) { + // do nothing + } + + @Override + public void setTrackedHeadsUp(ExpandableNotificationRow expandableNotificationRow) { + setTrackingHeadsUp(expandableNotificationRow); + } + + @Override + public void startExpand(float newX, float newY, boolean startTracking, + float expandedHeight) { + // do nothing + } + }; + } else { + headsUpViewController = new HeadsUpNotificationViewControllerEmptyImpl(); + } + return headsUpViewController; + } + @Override public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("mMaxAlphaFromView=" + mMaxAlphaFromView); 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 aee1d3e08256..0c2b5aeb6feb 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 @@ -16,8 +16,6 @@ package com.android.systemui.statusbar.notification.stack; -import static androidx.core.math.MathUtils.clamp; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -890,7 +888,14 @@ public class StackScrollAlgorithm { continue; } ExpandableViewState childState = row.getViewState(); - if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) { + boolean shouldSetTopHeadsUpEntry; + if (SceneContainerFlag.isEnabled()) { + shouldSetTopHeadsUpEntry = row.isHeadsUp(); + } else { + shouldSetTopHeadsUpEntry = row.mustStayOnScreen(); + } + if (topHeadsUpEntry == null && shouldSetTopHeadsUpEntry + && !childState.headsUpIsVisible) { topHeadsUpEntry = row; childState.location = ExpandableViewState.LOCATION_FIRST_HUN; } @@ -898,7 +903,7 @@ public class StackScrollAlgorithm { float unmodifiedEndLocation = childState.getYTranslation() + childState.height; if (mIsExpanded) { if (SceneContainerFlag.isEnabled()) { - if (shouldHunBeVisibleWhenScrolled(row.mustStayOnScreen(), + if (shouldHunBeVisibleWhenScrolled(row.isHeadsUp(), childState.headsUpIsVisible, row.showingPulsing(), ambientState.isOnKeyguard(), row.getEntry().isStickyAndNotDemoted())) { // the height of this child before clamping it to the top @@ -909,10 +914,19 @@ public class StackScrollAlgorithm { /* viewState = */ childState ); float baseZ = ambientState.getBaseZHeight(); - if (headsUpTranslation < ambientState.getStackTop()) { - // HUN displayed above the stack top, it needs a fix shadow - childState.setZTranslation(baseZ + mPinnedZTranslationExtra); - } else { + if (headsUpTranslation > ambientState.getStackTop() + && row.isAboveShelf()) { + // HUN displayed outside of the stack during transition from Gone/LS; + // add a shadow that corresponds to the transition progress. + float fraction = 1 - ambientState.getExpansionFraction(); + childState.setZTranslation(baseZ + fraction * mPinnedZTranslationExtra); + } else if (headsUpTranslation < ambientState.getStackTop() + && row.isAboveShelf()) { + // HUN displayed outside of the stack during transition from QS; + // add a shadow that corresponds to the transition progress. + float fraction = ambientState.getQsExpansionFraction(); + childState.setZTranslation(baseZ + fraction * mPinnedZTranslationExtra); + } else if (headsUpTranslation > ambientState.getStackTop()) { // HUN displayed within the stack, add a shadow if it overlaps with // other elements. // @@ -927,6 +941,8 @@ public class StackScrollAlgorithm { /* baseZ = */ baseZ, /* viewState = */ childState ); + } else { + childState.setZTranslation(baseZ); } if (isTopEntry && row.isAboveShelf()) { clampHunToMaxTranslation( @@ -1081,7 +1097,7 @@ public class StackScrollAlgorithm { if (scrollingContentTopPadding > 0f) { // scrollingContentTopPadding makes a gap between the bottom of the HUN and the top // of the scrolling content. Use this to animate to the full shadow. - shadowFraction = clamp(overlap / scrollingContentTopPadding, 0f, 1f); + shadowFraction = Math.clamp(overlap / scrollingContentTopPadding, 0f, 1f); } if (overlap > 0.0f) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt index 6226fe7952f6..288924dd4000 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt @@ -80,9 +80,15 @@ interface NotificationScrollView { /** sets the current expand fraction */ fun setExpandFraction(expandFraction: Float) + /** sets the current QS expand fraction */ + fun setQsExpandFraction(expandFraction: Float) + /** Sets whether the view is displayed in doze mode. */ fun setDozing(dozing: Boolean) + /** Gets the inset for HUNs when they are not visible */ + fun getHeadsUpInset(): Int + /** Adds a listener to be notified, when the stack height might have changed. */ fun addStackHeightChangedListener(runnable: Runnable) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt index 950b14d2fafc..40761e07e33c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt @@ -85,9 +85,14 @@ constructor( launch { viewModel.expandFraction.collect { view.setExpandFraction(it.coerceIn(0f, 1f)) } } + launch { viewModel.qsExpandFraction.collect { view.setQsExpandFraction(it) } } launch { viewModel.isScrollable.collect { view.setScrollingEnabled(it) } } launch { viewModel.isDozing.collect { isDozing -> view.setDozing(isDozing) } } - launch { viewModel.shouldResetStackTop.filter { it }.collect { view.setStackTop(0f) } } + launch { + viewModel.shouldResetStackTop + .filter { it } + .collect { view.setStackTop(-(view.getHeadsUpInset().toFloat())) } + } launchAndDispose { view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index ed69e6f1acef..6489264fc2a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -124,6 +124,9 @@ constructor( .distinctUntilChanged() .dumpWhileCollecting("expandFraction") + val qsExpandFraction: Flow<Float> = + shadeInteractor.qsExpansion.dumpWhileCollecting("qsExpandFraction") + val shouldResetStackTop: Flow<Boolean> = sceneInteractor.transitionState .mapNotNull { state -> 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 ad029d7e7ef2..7e790197ccd1 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 @@ -296,6 +296,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { collapsedHeight = 100, intrinsicHeight = intrinsicHunHeight, ) + ambientState.qsExpansionFraction = 1.0f whenever(notificationRow.isAboveShelf).thenReturn(true) // When |