Loading packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackContentHeight.kt 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.notifications.ui.composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Measurable import androidx.compose.ui.layout.MeasureResult import androidx.compose.ui.layout.MeasureScope import androidx.compose.ui.node.LayoutModifierNode import androidx.compose.ui.node.ModifierNodeElement import androidx.compose.ui.node.invalidateMeasurement import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.IntOffset import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView /** * Modify element, which updates the height to be the same as the Notification stack height returned * by the legacy Notification stack scroll view in [NotificationScrollView.intrinsicStackHeight]. * * @param view Notification stack scroll view * @param padding extra padding in pixels to be added to the received content height. */ fun Modifier.notificationStackHeight(view: NotificationScrollView, padding: Int = 0) = this then StackLayoutElement(view, padding) private data class StackLayoutElement( val view: NotificationScrollView, val padding: Int, ) : ModifierNodeElement<StackLayoutNode>() { override fun create(): StackLayoutNode = StackLayoutNode(view, padding) override fun update(node: StackLayoutNode) { check(view == node.view) { "Trying to reuse the node with a new View." } if (node.padding != padding) { node.padding = padding node.invalidateMeasureIfAttached() } } } private class StackLayoutNode(val view: NotificationScrollView, var padding: Int) : LayoutModifierNode, Modifier.Node() { private val stackHeightChangedListener = Runnable { invalidateMeasureIfAttached() } override fun onAttach() { super.onAttach() view.addStackHeightChangedListener(stackHeightChangedListener) } override fun onDetach() { super.onDetach() view.removeStackHeightChangedListener(stackHeightChangedListener) } override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { val contentHeight = padding + view.intrinsicStackHeight val placeable = measurable.measure( constraints.copy(minHeight = contentHeight, maxHeight = contentHeight) ) return layout(placeable.width, placeable.height) { placeable.place(IntOffset.Zero) } } override fun toString(): String { return "StackLayoutNode(view=$view padding:$padding)" } fun invalidateMeasureIfAttached() { if (isAttached) { this.invalidateMeasurement() } } } packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +17 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment Loading Loading @@ -75,6 +77,7 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.ui.composable.ShadeHeader import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel Loading Loading @@ -158,6 +161,7 @@ fun SceneScope.ConstrainedNotificationStack( @Composable fun SceneScope.NotificationScrollingStack( shadeSession: SaveableSession, stackScrollView: NotificationScrollView, viewModel: NotificationsPlaceholderViewModel, maxScrimTop: () -> Float, shouldPunchHoleBehindScrim: Boolean, Loading @@ -179,7 +183,12 @@ fun SceneScope.NotificationScrollingStack( with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val screenHeight = LocalRawScreenHeight.current val stackHeight = viewModel.stackHeight.collectAsState() /** * The height in px of the contents of notification stack. Depending on the number of * notifications, this can exceed the space available on screen to show notifications, at which * point the notification stack should become scrollable. */ val stackHeight = remember { mutableIntStateOf(0) } val scrimRounding = viewModel.shadeScrimRounding.collectAsState(ShadeScrimRounding()) Loading Loading @@ -212,7 +221,7 @@ fun SceneScope.NotificationScrollingStack( // if contentHeight drops below minimum visible scrim height while scrim is // expanded, reset scrim offset. LaunchedEffect(stackHeight, scrimOffset) { snapshotFlow { stackHeight.value < minVisibleScrimHeight() && scrimOffset.value < 0f } snapshotFlow { stackHeight.intValue < minVisibleScrimHeight() && scrimOffset.value < 0f } .collect { shouldCollapse -> if (shouldCollapse) scrimOffset.snapTo(0f) } } Loading Loading @@ -324,7 +333,7 @@ fun SceneScope.NotificationScrollingStack( }, minScrimOffset = minScrimOffset, maxScrimOffset = 0f, contentHeight = { stackHeight.value }, contentHeight = { stackHeight.intValue.toFloat() }, minVisibleScrimHeight = minVisibleScrimHeight, isCurrentGestureOverscroll = { isCurrentGestureOverscroll.value Loading @@ -334,7 +343,11 @@ fun SceneScope.NotificationScrollingStack( ) .verticalScroll(scrollState) .fillMaxWidth() .height { (stackHeight.value + navBarHeight).roundToInt() }, .notificationStackHeight( view = stackScrollView, padding = navBarHeight.toInt() ) .onSizeChanged { size -> stackHeight.intValue = size.height }, ) } HeadsUpNotificationSpace(viewModel = viewModel) Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +6 −0 Original line number Diff line number Diff line Loading @@ -90,10 +90,12 @@ import com.android.systemui.shade.ui.composable.CollapsedShadeHeader import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.shade.ui.composable.ShadeHeader import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt Loading @@ -108,6 +110,7 @@ class QuickSettingsScene constructor( @Application private val applicationScope: CoroutineScope, private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, Loading @@ -130,6 +133,7 @@ constructor( modifier: Modifier, ) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModel = viewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, createTintedIconManager = tintedIconManagerFactory::create, Loading @@ -145,6 +149,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, viewModel: QuickSettingsSceneViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, Loading Loading @@ -360,6 +365,7 @@ private fun SceneScope.QuickSettingsScene( ) } NotificationScrollingStack( stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, shadeSession = shadeSession, maxScrimTop = { screenHeight }, Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +11 −0 Original line number Diff line number Diff line Loading @@ -88,9 +88,11 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt Loading Loading @@ -126,6 +128,7 @@ class ShadeScene @Inject constructor( private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val viewModel: ShadeSceneViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, Loading @@ -144,6 +147,7 @@ constructor( modifier: Modifier, ) = ShadeScene( notificationStackScrollView.get(), viewModel = viewModel, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, Loading @@ -163,6 +167,7 @@ constructor( @Composable private fun SceneScope.ShadeScene( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading @@ -176,6 +181,7 @@ private fun SceneScope.ShadeScene( when (shadeMode) { is ShadeMode.Single -> SingleShade( notificationStackScrollView = notificationStackScrollView, viewModel = viewModel, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, Loading @@ -187,6 +193,7 @@ private fun SceneScope.ShadeScene( ) is ShadeMode.Split -> SplitShade( notificationStackScrollView = notificationStackScrollView, viewModel = viewModel, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, Loading @@ -202,6 +209,7 @@ private fun SceneScope.ShadeScene( @Composable private fun SceneScope.SingleShade( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading Loading @@ -287,6 +295,7 @@ private fun SceneScope.SingleShade( { NotificationScrollingStack( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = viewModel.notifications, maxScrimTop = { maxNotifScrimTop.value }, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, Loading @@ -313,6 +322,7 @@ private fun SceneScope.SingleShade( @Composable private fun SceneScope.SplitShade( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading Loading @@ -478,6 +488,7 @@ private fun SceneScope.SplitShade( NotificationScrollingStack( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = viewModel.notifications, maxScrimTop = { 0f }, shouldPunchHoleBehindScrim = false, Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +37 −9 Original line number Diff line number Diff line Loading @@ -128,6 +128,7 @@ import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.util.Assert; import com.android.systemui.util.ColorUtilKt; import com.android.systemui.util.DumpUtilsKt; import com.android.systemui.util.ListenerSet; import com.google.errorprone.annotations.CompileTimeConstant; Loading Loading @@ -254,6 +255,7 @@ public class NotificationStackScrollLayout * The raw amount of the overScroll on the bottom, which is not rubber-banded. */ private float mOverScrolledBottomPixels; private ListenerSet<Runnable> mStackHeightChangedListeners = new ListenerSet<>(); private NotificationLogger.OnChildLocationsChangedListener mListener; private OnNotificationLocationsChangedListener mLocationsChangedListener; private OnOverscrollTopChangedListener mOverscrollTopChangedListener; Loading Loading @@ -316,7 +318,7 @@ public class NotificationStackScrollLayout = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (SceneContainerFlag.isEnabled() && !mChildrenUpdateRequested) { if (SceneContainerFlag.isEnabled()) { getViewTreeObserver().removeOnPreDrawListener(this); return true; } Loading Loading @@ -1083,6 +1085,10 @@ public class NotificationStackScrollLayout for (int i = 0; i < size; i++) { measureChild(getChildAt(i), childWidthSpec, childHeightSpec); } if (SceneContainerFlag.isEnabled()) { setMaxLayoutHeight(getMeasuredHeight()); updateContentHeight(); } Trace.endSection(); } Loading @@ -1092,6 +1098,22 @@ public class NotificationStackScrollLayout super.requestLayout(); } private void notifyStackHeightChangedListeners() { for (Runnable listener : mStackHeightChangedListeners) { listener.run(); } } @Override public void addStackHeightChangedListener(@NonNull Runnable runnable) { mStackHeightChangedListeners.addIfAbsent(runnable); } @Override public void removeStackHeightChangedListener(@NonNull Runnable runnable) { mStackHeightChangedListeners.remove(runnable); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (!mSuppressChildrenMeasureAndLayout) { Loading @@ -1110,8 +1132,10 @@ public class NotificationStackScrollLayout (int) height); } } if (!SceneContainerFlag.isEnabled()) { setMaxLayoutHeight(getHeight()); updateContentHeight(); } clampScrollPosition(); requestChildrenUpdate(); updateFirstAndLastBackgroundViews(); Loading Loading @@ -1176,11 +1200,6 @@ public class NotificationStackScrollLayout mScrollViewFields.setCurrentGestureOverscrollConsumer(consumer); } @Override public void setStackHeightConsumer(@Nullable Consumer<Float> consumer) { mScrollViewFields.setStackHeightConsumer(consumer); } @Override public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) { mScrollViewFields.setHeadsUpHeightConsumer(consumer); Loading Loading @@ -2404,16 +2423,25 @@ public class NotificationStackScrollLayout /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications, shelfIntrinsicHeight); mIntrinsicContentHeight = height; mScrollViewFields.sendStackHeight(height + footerIntrinsicHeight); // The topPadding can be bigger than the regular padding when qs is expanded, in that // state the maxPanelHeight and the contentHeight should be bigger mContentHeight = (int) (height + Math.max(mIntrinsicPadding, getTopPadding()) + mBottomPadding); mScrollViewFields.setIntrinsicStackHeight( (int) (mIntrinsicPadding + mIntrinsicContentHeight + footerIntrinsicHeight + mBottomPadding)); updateScrollability(); clampScrollPosition(); updateStackPosition(); mAmbientState.setContentHeight(mContentHeight); notifyStackHeightChangedListeners(); } @Override public int getIntrinsicStackHeight() { return mScrollViewFields.getIntrinsicStackHeight(); } /** Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackContentHeight.kt 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.notifications.ui.composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Measurable import androidx.compose.ui.layout.MeasureResult import androidx.compose.ui.layout.MeasureScope import androidx.compose.ui.node.LayoutModifierNode import androidx.compose.ui.node.ModifierNodeElement import androidx.compose.ui.node.invalidateMeasurement import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.IntOffset import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView /** * Modify element, which updates the height to be the same as the Notification stack height returned * by the legacy Notification stack scroll view in [NotificationScrollView.intrinsicStackHeight]. * * @param view Notification stack scroll view * @param padding extra padding in pixels to be added to the received content height. */ fun Modifier.notificationStackHeight(view: NotificationScrollView, padding: Int = 0) = this then StackLayoutElement(view, padding) private data class StackLayoutElement( val view: NotificationScrollView, val padding: Int, ) : ModifierNodeElement<StackLayoutNode>() { override fun create(): StackLayoutNode = StackLayoutNode(view, padding) override fun update(node: StackLayoutNode) { check(view == node.view) { "Trying to reuse the node with a new View." } if (node.padding != padding) { node.padding = padding node.invalidateMeasureIfAttached() } } } private class StackLayoutNode(val view: NotificationScrollView, var padding: Int) : LayoutModifierNode, Modifier.Node() { private val stackHeightChangedListener = Runnable { invalidateMeasureIfAttached() } override fun onAttach() { super.onAttach() view.addStackHeightChangedListener(stackHeightChangedListener) } override fun onDetach() { super.onDetach() view.removeStackHeightChangedListener(stackHeightChangedListener) } override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { val contentHeight = padding + view.intrinsicStackHeight val placeable = measurable.measure( constraints.copy(minHeight = contentHeight, maxHeight = contentHeight) ) return layout(placeable.width, placeable.height) { placeable.place(IntOffset.Zero) } } override fun toString(): String { return "StackLayoutNode(view=$view padding:$padding)" } fun invalidateMeasureIfAttached() { if (isAttached) { this.invalidateMeasurement() } } }
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +17 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment Loading Loading @@ -75,6 +77,7 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.ui.composable.ShadeHeader import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel Loading Loading @@ -158,6 +161,7 @@ fun SceneScope.ConstrainedNotificationStack( @Composable fun SceneScope.NotificationScrollingStack( shadeSession: SaveableSession, stackScrollView: NotificationScrollView, viewModel: NotificationsPlaceholderViewModel, maxScrimTop: () -> Float, shouldPunchHoleBehindScrim: Boolean, Loading @@ -179,7 +183,12 @@ fun SceneScope.NotificationScrollingStack( with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val screenHeight = LocalRawScreenHeight.current val stackHeight = viewModel.stackHeight.collectAsState() /** * The height in px of the contents of notification stack. Depending on the number of * notifications, this can exceed the space available on screen to show notifications, at which * point the notification stack should become scrollable. */ val stackHeight = remember { mutableIntStateOf(0) } val scrimRounding = viewModel.shadeScrimRounding.collectAsState(ShadeScrimRounding()) Loading Loading @@ -212,7 +221,7 @@ fun SceneScope.NotificationScrollingStack( // if contentHeight drops below minimum visible scrim height while scrim is // expanded, reset scrim offset. LaunchedEffect(stackHeight, scrimOffset) { snapshotFlow { stackHeight.value < minVisibleScrimHeight() && scrimOffset.value < 0f } snapshotFlow { stackHeight.intValue < minVisibleScrimHeight() && scrimOffset.value < 0f } .collect { shouldCollapse -> if (shouldCollapse) scrimOffset.snapTo(0f) } } Loading Loading @@ -324,7 +333,7 @@ fun SceneScope.NotificationScrollingStack( }, minScrimOffset = minScrimOffset, maxScrimOffset = 0f, contentHeight = { stackHeight.value }, contentHeight = { stackHeight.intValue.toFloat() }, minVisibleScrimHeight = minVisibleScrimHeight, isCurrentGestureOverscroll = { isCurrentGestureOverscroll.value Loading @@ -334,7 +343,11 @@ fun SceneScope.NotificationScrollingStack( ) .verticalScroll(scrollState) .fillMaxWidth() .height { (stackHeight.value + navBarHeight).roundToInt() }, .notificationStackHeight( view = stackScrollView, padding = navBarHeight.toInt() ) .onSizeChanged { size -> stackHeight.intValue = size.height }, ) } HeadsUpNotificationSpace(viewModel = viewModel) Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +6 −0 Original line number Diff line number Diff line Loading @@ -90,10 +90,12 @@ import com.android.systemui.shade.ui.composable.CollapsedShadeHeader import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.shade.ui.composable.ShadeHeader import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt Loading @@ -108,6 +110,7 @@ class QuickSettingsScene constructor( @Application private val applicationScope: CoroutineScope, private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, Loading @@ -130,6 +133,7 @@ constructor( modifier: Modifier, ) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModel = viewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, createTintedIconManager = tintedIconManagerFactory::create, Loading @@ -145,6 +149,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, viewModel: QuickSettingsSceneViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, Loading Loading @@ -360,6 +365,7 @@ private fun SceneScope.QuickSettingsScene( ) } NotificationScrollingStack( stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, shadeSession = shadeSession, maxScrimTop = { screenHeight }, Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +11 −0 Original line number Diff line number Diff line Loading @@ -88,9 +88,11 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt Loading Loading @@ -126,6 +128,7 @@ class ShadeScene @Inject constructor( private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val viewModel: ShadeSceneViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, Loading @@ -144,6 +147,7 @@ constructor( modifier: Modifier, ) = ShadeScene( notificationStackScrollView.get(), viewModel = viewModel, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, Loading @@ -163,6 +167,7 @@ constructor( @Composable private fun SceneScope.ShadeScene( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading @@ -176,6 +181,7 @@ private fun SceneScope.ShadeScene( when (shadeMode) { is ShadeMode.Single -> SingleShade( notificationStackScrollView = notificationStackScrollView, viewModel = viewModel, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, Loading @@ -187,6 +193,7 @@ private fun SceneScope.ShadeScene( ) is ShadeMode.Split -> SplitShade( notificationStackScrollView = notificationStackScrollView, viewModel = viewModel, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, Loading @@ -202,6 +209,7 @@ private fun SceneScope.ShadeScene( @Composable private fun SceneScope.SingleShade( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading Loading @@ -287,6 +295,7 @@ private fun SceneScope.SingleShade( { NotificationScrollingStack( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = viewModel.notifications, maxScrimTop = { maxNotifScrimTop.value }, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, Loading @@ -313,6 +322,7 @@ private fun SceneScope.SingleShade( @Composable private fun SceneScope.SplitShade( notificationStackScrollView: NotificationScrollView, viewModel: ShadeSceneViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, Loading Loading @@ -478,6 +488,7 @@ private fun SceneScope.SplitShade( NotificationScrollingStack( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = viewModel.notifications, maxScrimTop = { 0f }, shouldPunchHoleBehindScrim = false, Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +37 −9 Original line number Diff line number Diff line Loading @@ -128,6 +128,7 @@ import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.util.Assert; import com.android.systemui.util.ColorUtilKt; import com.android.systemui.util.DumpUtilsKt; import com.android.systemui.util.ListenerSet; import com.google.errorprone.annotations.CompileTimeConstant; Loading Loading @@ -254,6 +255,7 @@ public class NotificationStackScrollLayout * The raw amount of the overScroll on the bottom, which is not rubber-banded. */ private float mOverScrolledBottomPixels; private ListenerSet<Runnable> mStackHeightChangedListeners = new ListenerSet<>(); private NotificationLogger.OnChildLocationsChangedListener mListener; private OnNotificationLocationsChangedListener mLocationsChangedListener; private OnOverscrollTopChangedListener mOverscrollTopChangedListener; Loading Loading @@ -316,7 +318,7 @@ public class NotificationStackScrollLayout = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (SceneContainerFlag.isEnabled() && !mChildrenUpdateRequested) { if (SceneContainerFlag.isEnabled()) { getViewTreeObserver().removeOnPreDrawListener(this); return true; } Loading Loading @@ -1083,6 +1085,10 @@ public class NotificationStackScrollLayout for (int i = 0; i < size; i++) { measureChild(getChildAt(i), childWidthSpec, childHeightSpec); } if (SceneContainerFlag.isEnabled()) { setMaxLayoutHeight(getMeasuredHeight()); updateContentHeight(); } Trace.endSection(); } Loading @@ -1092,6 +1098,22 @@ public class NotificationStackScrollLayout super.requestLayout(); } private void notifyStackHeightChangedListeners() { for (Runnable listener : mStackHeightChangedListeners) { listener.run(); } } @Override public void addStackHeightChangedListener(@NonNull Runnable runnable) { mStackHeightChangedListeners.addIfAbsent(runnable); } @Override public void removeStackHeightChangedListener(@NonNull Runnable runnable) { mStackHeightChangedListeners.remove(runnable); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (!mSuppressChildrenMeasureAndLayout) { Loading @@ -1110,8 +1132,10 @@ public class NotificationStackScrollLayout (int) height); } } if (!SceneContainerFlag.isEnabled()) { setMaxLayoutHeight(getHeight()); updateContentHeight(); } clampScrollPosition(); requestChildrenUpdate(); updateFirstAndLastBackgroundViews(); Loading Loading @@ -1176,11 +1200,6 @@ public class NotificationStackScrollLayout mScrollViewFields.setCurrentGestureOverscrollConsumer(consumer); } @Override public void setStackHeightConsumer(@Nullable Consumer<Float> consumer) { mScrollViewFields.setStackHeightConsumer(consumer); } @Override public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) { mScrollViewFields.setHeadsUpHeightConsumer(consumer); Loading Loading @@ -2404,16 +2423,25 @@ public class NotificationStackScrollLayout /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications, shelfIntrinsicHeight); mIntrinsicContentHeight = height; mScrollViewFields.sendStackHeight(height + footerIntrinsicHeight); // The topPadding can be bigger than the regular padding when qs is expanded, in that // state the maxPanelHeight and the contentHeight should be bigger mContentHeight = (int) (height + Math.max(mIntrinsicPadding, getTopPadding()) + mBottomPadding); mScrollViewFields.setIntrinsicStackHeight( (int) (mIntrinsicPadding + mIntrinsicContentHeight + footerIntrinsicHeight + mBottomPadding)); updateScrollability(); clampScrollPosition(); updateStackPosition(); mAmbientState.setContentHeight(mContentHeight); notifyStackHeightChangedListeners(); } @Override public int getIntrinsicStackHeight() { return mScrollViewFields.getIntrinsicStackHeight(); } /** Loading