Loading packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt +7 −19 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn Loading @@ -44,10 +43,7 @@ import com.android.systemui.scene.ui.composable.Overlay import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.shade.ui.composable.OverlayShadeHeader import com.android.systemui.shade.ui.composable.SingleShadeMeasurePolicy import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.flow.Flow Loading @@ -58,11 +54,6 @@ class NotificationsShadeOverlay constructor( private val actionsViewModelFactory: NotificationsShadeOverlayActionsViewModel.Factory, private val contentViewModelFactory: NotificationsShadeOverlayContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder, private val shadeSession: SaveableSession, private val stackScrollView: Lazy<NotificationScrollView>, private val clockSection: DefaultClockSection, Loading Loading @@ -94,18 +85,16 @@ constructor( } OverlayShade( isShadeLayoutWide = viewModel.isShadeLayoutWide, panelAlignment = Alignment.TopStart, modifier = modifier, onScrimClicked = viewModel::onScrimClicked, header = { val headerViewModel = rememberViewModel("NotificationsShadeOverlayHeader") { viewModel.shadeHeaderViewModelFactory.create() } OverlayShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, notificationIconContainerStatusBarViewBinder = notificationIconContainerStatusBarViewBinder, viewModel = headerViewModel, modifier = Modifier.element(NotificationsShade.Elements.StatusBar) .layoutId(SingleShadeMeasurePolicy.LayoutId.ShadeHeader), Loading @@ -114,7 +103,7 @@ constructor( ) { Box { Column { if (viewModel.showHeader) { if (viewModel.showClock) { val burnIn = rememberBurnIn(clockInteractor) with(clockSection) { Loading @@ -140,8 +129,7 @@ constructor( modifier = Modifier.fillMaxWidth(), ) } // Communicates the bottom position of the drawable area within the shade to // NSSL. // Communicates the bottom position of the drawable area within the shade to NSSL. NotificationStackCutoffGuideline( stackScrollView = stackScrollView.get(), viewModel = placeholderViewModel, Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +26 −40 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.qs.ui.composable import android.view.ViewGroup import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateDpAsState Loading Loading @@ -76,7 +75,6 @@ import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.modifiers.thenIf import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout import com.android.systemui.compose.modifiers.sysuiResTag Loading @@ -100,15 +98,14 @@ import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel 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.shade.ui.viewmodel.ShadeHeaderViewModel 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 Loading @@ -125,9 +122,6 @@ constructor( private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, private val actionsViewModelFactory: QuickSettingsUserActionsViewModel.Factory, private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val mediaCarouselController: MediaCarouselController, @Named(MediaModule.QS_PANEL) private val mediaHost: MediaHost, ) : ExclusiveActivatable(), Scene { Loading @@ -145,16 +139,26 @@ constructor( @Composable override fun ContentScope.Content(modifier: Modifier) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModelFactory = contentViewModelFactory, notificationsPlaceholderViewModel = val viewModel = rememberViewModel("QuickSettingsScene-viewModel") { contentViewModelFactory.create() } val headerViewModel = rememberViewModel("QuickSettingsScene-headerViewModel") { viewModel.shadeHeaderViewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") { viewModel.brightnessMirrorViewModelFactory.create() } val notificationsPlaceholderViewModel = rememberViewModel("QuickSettingsScene-notifPlaceholderViewModel") { notificationsPlaceholderViewModelFactory.create() }, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, } QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModel = viewModel, headerViewModel = headerViewModel, brightnessMirrorViewModel = brightnessMirrorViewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, mediaCarouselController = mediaCarouselController, mediaHost = mediaHost, modifier = modifier, Loading @@ -166,23 +170,16 @@ constructor( @Composable private fun ContentScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, viewModelFactory: QuickSettingsSceneContentViewModel.Factory, viewModel: QuickSettingsSceneContentViewModel, headerViewModel: ShadeHeaderViewModel, brightnessMirrorViewModel: BrightnessMirrorViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, statusBarIconController: StatusBarIconController, mediaCarouselController: MediaCarouselController, mediaHost: MediaHost, modifier: Modifier = Modifier, shadeSession: SaveableSession, ) { val cutoutLocation = LocalDisplayCutout.current.location val viewModel = rememberViewModel("QuickSettingsScene-viewModel") { viewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") { viewModel.brightnessMirrorViewModelFactory.create() } val brightnessMirrorShowing by brightnessMirrorViewModel.isShowing.collectAsStateWithLifecycle() val contentAlpha by animateFloatAsState( Loading Loading @@ -222,8 +219,7 @@ private fun ContentScope.QuickSettingsScene( .graphicsLayer { alpha = contentAlpha } .thenIf(shouldPunchHoleBehindScrim) { // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears // this // scene (and not the one under it) during a scene transition. // this scene (and not the one under it) during a scene transition. Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) } .thenIf(cutoutLocation != CutoutLocation.CENTER) { Modifier.displayCutoutPadding() } Loading Loading @@ -348,21 +344,11 @@ private fun ContentScope.QuickSettingsScene( fadeOut(tween(customizingAnimationDuration)), ) { ExpandedShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, viewModel = headerViewModel, modifier = Modifier.padding(horizontal = 16.dp), ) } else -> CollapsedShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, ) else -> CollapsedShadeHeader(viewModel = headerViewModel) } Spacer(modifier = Modifier.height(16.dp)) // This view has its own horizontal padding Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt +19 −29 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton Loading @@ -67,13 +66,10 @@ import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.shade.ui.composable.OverlayShadeHeader import com.android.systemui.shade.ui.composable.QuickSettingsOverlayHeader import com.android.systemui.shade.ui.composable.SingleShadeMeasurePolicy import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape 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.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.flow.Flow Loading @@ -84,11 +80,7 @@ class QuickSettingsShadeOverlay constructor( private val actionsViewModelFactory: QuickSettingsShadeOverlayActionsViewModel.Factory, private val contentViewModelFactory: QuickSettingsShadeOverlayContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder, private val quickSettingsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, ) : Overlay { Loading @@ -107,35 +99,35 @@ constructor( @Composable override fun ContentScope.Content(modifier: Modifier) { val viewModel = rememberViewModel("QuickSettingsShadeOverlay") { contentViewModelFactory.create() } val contentViewModel = rememberViewModel("QuickSettingsShadeOverlayContent") { contentViewModelFactory.create() } val quickSettingsContainerViewModel = rememberViewModel("QuickSettingsShadeOverlayContainer") { // TODO(b/393054014): Add support for brightness mirroring. quickSettingsContainerViewModelFactory.create(supportsBrightnessMirroring = false) } val panelCornerRadius = with(LocalDensity.current) { OverlayShade.Dimensions.PanelCornerRadius.toPx().toInt() } // set the bounds to null when the QuickSettings overlay disappears DisposableEffect(Unit) { onDispose { viewModel.onPanelShapeChanged(null) } } // Set the bounds to null when the QuickSettings overlay disappears. DisposableEffect(Unit) { onDispose { contentViewModel.onPanelShapeChanged(null) } } Box(modifier = modifier) { SnoozeableHeadsUpNotificationSpace( stackScrollView = notificationStackScrollView.get(), viewModel = rememberViewModel("QuickSettingsShadeOverlay") { rememberViewModel("QuickSettingsShadeOverlayPlaceholder") { notificationsPlaceholderViewModelFactory.create() }, ) OverlayShade( isShadeLayoutWide = viewModel.isShadeLayoutWide, panelAlignment = Alignment.TopEnd, onScrimClicked = viewModel::onScrimClicked, onScrimClicked = contentViewModel::onScrimClicked, header = { OverlayShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, notificationIconContainerStatusBarViewBinder = notificationIconContainerStatusBarViewBinder, viewModel = quickSettingsContainerViewModel.shadeHeaderViewModel, modifier = Modifier.element(NotificationsShade.Elements.StatusBar) .layoutId(SingleShadeMeasurePolicy.LayoutId.ShadeHeader), Loading @@ -143,7 +135,7 @@ constructor( }, ) { ShadeBody( viewModel = viewModel.quickSettingsContainerViewModel, viewModel = quickSettingsContainerViewModel, modifier = Modifier.onPlaced { coordinates -> val boundsInWindow = coordinates.boundsInWindow() Loading @@ -160,14 +152,12 @@ constructor( topRadius = 0, bottomRadius = panelCornerRadius, ) viewModel.onPanelShapeChanged(shape) contentViewModel.onPanelShapeChanged(shape) }, header = { if (viewModel.isShadeLayoutWide) { if (quickSettingsContainerViewModel.showHeader) { QuickSettingsOverlayHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, viewModel = quickSettingsContainerViewModel.shadeHeaderViewModel, modifier = Modifier.padding(top = QuickSettingsShade.Dimensions.Padding), ) Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt +22 −29 Original line number Diff line number Diff line Loading @@ -58,29 +58,31 @@ import com.android.systemui.res.R /** Renders a lightweight shade UI container, as an overlay. */ @Composable fun ContentScope.OverlayShade( isShadeLayoutWide: Boolean, panelAlignment: Alignment, onScrimClicked: () -> Unit, modifier: Modifier = Modifier, header: @Composable () -> Unit, content: @Composable () -> Unit, ) { val isFullWidth = isFullWidthShade() Box(modifier) { Scrim(onClicked = onScrimClicked) Box(modifier = Modifier.fillMaxSize().panelPadding(), contentAlignment = panelAlignment) { Box( modifier = Modifier.fillMaxSize().panelContainerPadding(isFullWidth), contentAlignment = panelAlignment, ) { Panel( isShadeLayoutWide = isShadeLayoutWide, modifier = Modifier.overscroll(verticalOverscrollEffect) .element(OverlayShade.Elements.Panel) .panelSize(), header = header, .panelWidth(isFullWidth), header = header.takeIf { isFullWidth }, content = content, ) } if (isShadeLayoutWide) { if (!isFullWidth) { header() } } Loading @@ -100,9 +102,8 @@ private fun ContentScope.Scrim(onClicked: () -> Unit, modifier: Modifier = Modif @Composable private fun ContentScope.Panel( isShadeLayoutWide: Boolean, modifier: Modifier = Modifier, header: @Composable () -> Unit, header: (@Composable () -> Unit)?, content: @Composable () -> Unit, ) { Box(modifier = modifier.clip(OverlayShade.Shapes.RoundedCornerPanel)) { Loading @@ -117,9 +118,7 @@ private fun ContentScope.Panel( ) Column { if (!isShadeLayoutWide) { header() } header?.invoke() // This content is intentionally rendered as a separate element from the background in // order to allow for more flexibility when defining transitions. Loading @@ -129,14 +128,12 @@ private fun ContentScope.Panel( } @Composable private fun Modifier.panelSize(): Modifier { return this.then( if (isFullWidthShade()) { Modifier.fillMaxWidth() private fun Modifier.panelWidth(isFullWidthPanel: Boolean): Modifier { return if (isFullWidthPanel) { fillMaxWidth() } else { Modifier.width(dimensionResource(id = R.dimen.shade_panel_width)) width(dimensionResource(id = R.dimen.shade_panel_width)) } ) } @Composable Loading @@ -146,27 +143,23 @@ internal fun isFullWidthShade(): Boolean { } @Composable private fun Modifier.panelPadding(): Modifier { val widthSizeClass = LocalWindowSizeClass.current.widthSizeClass private fun Modifier.panelContainerPadding(isFullWidthPanel: Boolean): Modifier { if (isFullWidthPanel) { return this } val systemBars = WindowInsets.systemBarsIgnoringVisibility val displayCutout = WindowInsets.displayCutout val waterfall = WindowInsets.waterfall val horizontalPadding = PaddingValues(horizontal = dimensionResource(id = R.dimen.shade_panel_margin_horizontal)) val combinedPadding = return padding( combinePaddings( systemBars.asPaddingValues(), displayCutout.asPaddingValues(), waterfall.asPaddingValues(), horizontalPadding, ) return if (widthSizeClass == WindowWidthSizeClass.Compact) { padding(bottom = combinedPadding.calculateBottomPadding()) } else { padding(combinedPadding) } ) } /** Creates a union of [paddingValues] by using the max padding of each edge. */ Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt +7 −19 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn Loading @@ -44,10 +43,7 @@ import com.android.systemui.scene.ui.composable.Overlay import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.shade.ui.composable.OverlayShadeHeader import com.android.systemui.shade.ui.composable.SingleShadeMeasurePolicy import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.flow.Flow Loading @@ -58,11 +54,6 @@ class NotificationsShadeOverlay constructor( private val actionsViewModelFactory: NotificationsShadeOverlayActionsViewModel.Factory, private val contentViewModelFactory: NotificationsShadeOverlayContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder, private val shadeSession: SaveableSession, private val stackScrollView: Lazy<NotificationScrollView>, private val clockSection: DefaultClockSection, Loading Loading @@ -94,18 +85,16 @@ constructor( } OverlayShade( isShadeLayoutWide = viewModel.isShadeLayoutWide, panelAlignment = Alignment.TopStart, modifier = modifier, onScrimClicked = viewModel::onScrimClicked, header = { val headerViewModel = rememberViewModel("NotificationsShadeOverlayHeader") { viewModel.shadeHeaderViewModelFactory.create() } OverlayShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, notificationIconContainerStatusBarViewBinder = notificationIconContainerStatusBarViewBinder, viewModel = headerViewModel, modifier = Modifier.element(NotificationsShade.Elements.StatusBar) .layoutId(SingleShadeMeasurePolicy.LayoutId.ShadeHeader), Loading @@ -114,7 +103,7 @@ constructor( ) { Box { Column { if (viewModel.showHeader) { if (viewModel.showClock) { val burnIn = rememberBurnIn(clockInteractor) with(clockSection) { Loading @@ -140,8 +129,7 @@ constructor( modifier = Modifier.fillMaxWidth(), ) } // Communicates the bottom position of the drawable area within the shade to // NSSL. // Communicates the bottom position of the drawable area within the shade to NSSL. NotificationStackCutoffGuideline( stackScrollView = stackScrollView.get(), viewModel = placeholderViewModel, Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +26 −40 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.qs.ui.composable import android.view.ViewGroup import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateDpAsState Loading Loading @@ -76,7 +75,6 @@ import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.modifiers.thenIf import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout import com.android.systemui.compose.modifiers.sysuiResTag Loading @@ -100,15 +98,14 @@ import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel 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.shade.ui.viewmodel.ShadeHeaderViewModel 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 Loading @@ -125,9 +122,6 @@ constructor( private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, private val actionsViewModelFactory: QuickSettingsUserActionsViewModel.Factory, private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val mediaCarouselController: MediaCarouselController, @Named(MediaModule.QS_PANEL) private val mediaHost: MediaHost, ) : ExclusiveActivatable(), Scene { Loading @@ -145,16 +139,26 @@ constructor( @Composable override fun ContentScope.Content(modifier: Modifier) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModelFactory = contentViewModelFactory, notificationsPlaceholderViewModel = val viewModel = rememberViewModel("QuickSettingsScene-viewModel") { contentViewModelFactory.create() } val headerViewModel = rememberViewModel("QuickSettingsScene-headerViewModel") { viewModel.shadeHeaderViewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") { viewModel.brightnessMirrorViewModelFactory.create() } val notificationsPlaceholderViewModel = rememberViewModel("QuickSettingsScene-notifPlaceholderViewModel") { notificationsPlaceholderViewModelFactory.create() }, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, } QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), viewModel = viewModel, headerViewModel = headerViewModel, brightnessMirrorViewModel = brightnessMirrorViewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, mediaCarouselController = mediaCarouselController, mediaHost = mediaHost, modifier = modifier, Loading @@ -166,23 +170,16 @@ constructor( @Composable private fun ContentScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, viewModelFactory: QuickSettingsSceneContentViewModel.Factory, viewModel: QuickSettingsSceneContentViewModel, headerViewModel: ShadeHeaderViewModel, brightnessMirrorViewModel: BrightnessMirrorViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, statusBarIconController: StatusBarIconController, mediaCarouselController: MediaCarouselController, mediaHost: MediaHost, modifier: Modifier = Modifier, shadeSession: SaveableSession, ) { val cutoutLocation = LocalDisplayCutout.current.location val viewModel = rememberViewModel("QuickSettingsScene-viewModel") { viewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") { viewModel.brightnessMirrorViewModelFactory.create() } val brightnessMirrorShowing by brightnessMirrorViewModel.isShowing.collectAsStateWithLifecycle() val contentAlpha by animateFloatAsState( Loading Loading @@ -222,8 +219,7 @@ private fun ContentScope.QuickSettingsScene( .graphicsLayer { alpha = contentAlpha } .thenIf(shouldPunchHoleBehindScrim) { // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears // this // scene (and not the one under it) during a scene transition. // this scene (and not the one under it) during a scene transition. Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) } .thenIf(cutoutLocation != CutoutLocation.CENTER) { Modifier.displayCutoutPadding() } Loading Loading @@ -348,21 +344,11 @@ private fun ContentScope.QuickSettingsScene( fadeOut(tween(customizingAnimationDuration)), ) { ExpandedShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, viewModel = headerViewModel, modifier = Modifier.padding(horizontal = 16.dp), ) } else -> CollapsedShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, ) else -> CollapsedShadeHeader(viewModel = headerViewModel) } Spacer(modifier = Modifier.height(16.dp)) // This view has its own horizontal padding Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt +19 −29 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton Loading @@ -67,13 +66,10 @@ import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.shade.ui.composable.OverlayShadeHeader import com.android.systemui.shade.ui.composable.QuickSettingsOverlayHeader import com.android.systemui.shade.ui.composable.SingleShadeMeasurePolicy import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape 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.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.flow.Flow Loading @@ -84,11 +80,7 @@ class QuickSettingsShadeOverlay constructor( private val actionsViewModelFactory: QuickSettingsShadeOverlayActionsViewModel.Factory, private val contentViewModelFactory: QuickSettingsShadeOverlayContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, private val notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder, private val quickSettingsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory, private val notificationStackScrollView: Lazy<NotificationScrollView>, private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, ) : Overlay { Loading @@ -107,35 +99,35 @@ constructor( @Composable override fun ContentScope.Content(modifier: Modifier) { val viewModel = rememberViewModel("QuickSettingsShadeOverlay") { contentViewModelFactory.create() } val contentViewModel = rememberViewModel("QuickSettingsShadeOverlayContent") { contentViewModelFactory.create() } val quickSettingsContainerViewModel = rememberViewModel("QuickSettingsShadeOverlayContainer") { // TODO(b/393054014): Add support for brightness mirroring. quickSettingsContainerViewModelFactory.create(supportsBrightnessMirroring = false) } val panelCornerRadius = with(LocalDensity.current) { OverlayShade.Dimensions.PanelCornerRadius.toPx().toInt() } // set the bounds to null when the QuickSettings overlay disappears DisposableEffect(Unit) { onDispose { viewModel.onPanelShapeChanged(null) } } // Set the bounds to null when the QuickSettings overlay disappears. DisposableEffect(Unit) { onDispose { contentViewModel.onPanelShapeChanged(null) } } Box(modifier = modifier) { SnoozeableHeadsUpNotificationSpace( stackScrollView = notificationStackScrollView.get(), viewModel = rememberViewModel("QuickSettingsShadeOverlay") { rememberViewModel("QuickSettingsShadeOverlayPlaceholder") { notificationsPlaceholderViewModelFactory.create() }, ) OverlayShade( isShadeLayoutWide = viewModel.isShadeLayoutWide, panelAlignment = Alignment.TopEnd, onScrimClicked = viewModel::onScrimClicked, onScrimClicked = contentViewModel::onScrimClicked, header = { OverlayShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, notificationIconContainerStatusBarViewBinder = notificationIconContainerStatusBarViewBinder, viewModel = quickSettingsContainerViewModel.shadeHeaderViewModel, modifier = Modifier.element(NotificationsShade.Elements.StatusBar) .layoutId(SingleShadeMeasurePolicy.LayoutId.ShadeHeader), Loading @@ -143,7 +135,7 @@ constructor( }, ) { ShadeBody( viewModel = viewModel.quickSettingsContainerViewModel, viewModel = quickSettingsContainerViewModel, modifier = Modifier.onPlaced { coordinates -> val boundsInWindow = coordinates.boundsInWindow() Loading @@ -160,14 +152,12 @@ constructor( topRadius = 0, bottomRadius = panelCornerRadius, ) viewModel.onPanelShapeChanged(shape) contentViewModel.onPanelShapeChanged(shape) }, header = { if (viewModel.isShadeLayoutWide) { if (quickSettingsContainerViewModel.showHeader) { QuickSettingsOverlayHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, viewModel = quickSettingsContainerViewModel.shadeHeaderViewModel, modifier = Modifier.padding(top = QuickSettingsShade.Dimensions.Padding), ) Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt +22 −29 Original line number Diff line number Diff line Loading @@ -58,29 +58,31 @@ import com.android.systemui.res.R /** Renders a lightweight shade UI container, as an overlay. */ @Composable fun ContentScope.OverlayShade( isShadeLayoutWide: Boolean, panelAlignment: Alignment, onScrimClicked: () -> Unit, modifier: Modifier = Modifier, header: @Composable () -> Unit, content: @Composable () -> Unit, ) { val isFullWidth = isFullWidthShade() Box(modifier) { Scrim(onClicked = onScrimClicked) Box(modifier = Modifier.fillMaxSize().panelPadding(), contentAlignment = panelAlignment) { Box( modifier = Modifier.fillMaxSize().panelContainerPadding(isFullWidth), contentAlignment = panelAlignment, ) { Panel( isShadeLayoutWide = isShadeLayoutWide, modifier = Modifier.overscroll(verticalOverscrollEffect) .element(OverlayShade.Elements.Panel) .panelSize(), header = header, .panelWidth(isFullWidth), header = header.takeIf { isFullWidth }, content = content, ) } if (isShadeLayoutWide) { if (!isFullWidth) { header() } } Loading @@ -100,9 +102,8 @@ private fun ContentScope.Scrim(onClicked: () -> Unit, modifier: Modifier = Modif @Composable private fun ContentScope.Panel( isShadeLayoutWide: Boolean, modifier: Modifier = Modifier, header: @Composable () -> Unit, header: (@Composable () -> Unit)?, content: @Composable () -> Unit, ) { Box(modifier = modifier.clip(OverlayShade.Shapes.RoundedCornerPanel)) { Loading @@ -117,9 +118,7 @@ private fun ContentScope.Panel( ) Column { if (!isShadeLayoutWide) { header() } header?.invoke() // This content is intentionally rendered as a separate element from the background in // order to allow for more flexibility when defining transitions. Loading @@ -129,14 +128,12 @@ private fun ContentScope.Panel( } @Composable private fun Modifier.panelSize(): Modifier { return this.then( if (isFullWidthShade()) { Modifier.fillMaxWidth() private fun Modifier.panelWidth(isFullWidthPanel: Boolean): Modifier { return if (isFullWidthPanel) { fillMaxWidth() } else { Modifier.width(dimensionResource(id = R.dimen.shade_panel_width)) width(dimensionResource(id = R.dimen.shade_panel_width)) } ) } @Composable Loading @@ -146,27 +143,23 @@ internal fun isFullWidthShade(): Boolean { } @Composable private fun Modifier.panelPadding(): Modifier { val widthSizeClass = LocalWindowSizeClass.current.widthSizeClass private fun Modifier.panelContainerPadding(isFullWidthPanel: Boolean): Modifier { if (isFullWidthPanel) { return this } val systemBars = WindowInsets.systemBarsIgnoringVisibility val displayCutout = WindowInsets.displayCutout val waterfall = WindowInsets.waterfall val horizontalPadding = PaddingValues(horizontal = dimensionResource(id = R.dimen.shade_panel_margin_horizontal)) val combinedPadding = return padding( combinePaddings( systemBars.asPaddingValues(), displayCutout.asPaddingValues(), waterfall.asPaddingValues(), horizontalPadding, ) return if (widthSizeClass == WindowWidthSizeClass.Compact) { padding(bottom = combinedPadding.calculateBottomPadding()) } else { padding(combinedPadding) } ) } /** Creates a union of [paddingValues] by using the max padding of each edge. */ Loading