Loading packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt +23 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,16 @@ package com.android.systemui.common.ui.compose.windowinsets import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import kotlinx.coroutines.flow.StateFlow Loading @@ -31,6 +36,9 @@ val LocalDisplayCutout = staticCompositionLocalOf { DisplayCutout() } /** The corner radius in px of the current display. */ val LocalScreenCornerRadius = staticCompositionLocalOf { 0.dp } /** The screen height in px without accounting for any screen insets (cutouts, status/nav bars) */ val LocalRawScreenHeight = staticCompositionLocalOf { 0f } @Composable fun ScreenDecorProvider( displayCutout: StateFlow<DisplayCutout>, Loading @@ -39,9 +47,23 @@ fun ScreenDecorProvider( ) { val cutout by displayCutout.collectAsState() val screenCornerRadiusDp = with(LocalDensity.current) { screenCornerRadius.toDp() } val density = LocalDensity.current val navBarHeight = with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding() val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding() val screenHeight = with(density) { (LocalConfiguration.current.screenHeightDp.dp + maxOf(statusBarHeight, displayCutoutHeight)) .toPx() } + navBarHeight CompositionLocalProvider( LocalScreenCornerRadius provides screenCornerRadiusDp, LocalDisplayCutout provides cutout LocalDisplayCutout provides cutout, LocalRawScreenHeight provides screenHeight, ) { content() } Loading packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +15 −15 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset Loading Loading @@ -57,7 +56,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.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp Loading @@ -67,15 +65,17 @@ import androidx.compose.ui.util.lerp import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.NestedScrollBehavior import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.SceneTransitionLayoutState import com.android.compose.modifiers.height import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.res.R 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.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 import kotlin.math.roundToInt Loading Loading @@ -168,14 +168,7 @@ fun SceneScope.NotificationScrollingStack( val navBarHeight = with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding() val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding() val screenHeight = with(density) { (LocalConfiguration.current.screenHeightDp.dp + maxOf(statusBarHeight, displayCutoutHeight)) .toPx() } + navBarHeight val screenHeight = LocalRawScreenHeight.current val stackHeight = viewModel.stackHeight.collectAsState() Loading Loading @@ -253,7 +246,7 @@ fun SceneScope.NotificationScrollingStack( scrimCornerRadius, screenCornerRadius, { expansionFraction }, layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) layoutState.isNotificationScrimTransitioning(), ) .let { scrimRounding.value.toRoundedCornerShape(it) } clip = true Loading Loading @@ -288,7 +281,7 @@ fun SceneScope.NotificationScrollingStack( Modifier.fillMaxSize() .graphicsLayer { alpha = if (layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade)) { if (layoutState.isNotificationScrimTransitioning()) { (expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f) } else 1f } Loading Loading @@ -425,7 +418,7 @@ private fun Modifier.debugBackground( this } fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { private fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { val topRadius = if (isTopRounded) radius else 0.dp val bottomRadius = if (isBottomRounded) radius else 0.dp return RoundedCornerShape( Loading @@ -436,6 +429,13 @@ fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { ) } private fun SceneTransitionLayoutState.isNotificationScrimTransitioning(): Boolean { return isTransitioningBetween(Scenes.Gone, Scenes.Shade) || isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade) || isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) || isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings) } private const val TAG = "FlexiNotifs" private val DEBUG_STACK_COLOR = Color(1f, 0f, 0f, 0.2f) private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f) Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +26 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState Loading @@ -50,19 +51,23 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.CompositingStrategy import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.colorResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.TransitionState import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.notifications.ui.composable.NotificationScrollingStack import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel import com.android.systemui.res.R Loading @@ -72,10 +77,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.viewmodel.NotificationsPlaceholderViewModel import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager import com.android.systemui.statusbar.phone.StatusBarLocation import javax.inject.Inject import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn Loading @@ -87,6 +94,7 @@ class QuickSettingsScene constructor( @Application private val applicationScope: CoroutineScope, private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, Loading @@ -106,6 +114,7 @@ constructor( ) { QuickSettingsScene( viewModel = viewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, Loading @@ -117,6 +126,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( viewModel: QuickSettingsSceneViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, statusBarIconController: StatusBarIconController, Loading @@ -135,8 +145,17 @@ private fun SceneScope.QuickSettingsScene( ) // TODO(b/280887232): implement the real UI. Box(modifier = modifier.fillMaxSize().graphicsLayer { alpha = contentAlpha }) { Box( modifier = modifier.fillMaxSize().graphicsLayer { // 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. compositingStrategy = CompositingStrategy.Offscreen alpha = contentAlpha } ) { val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState() val screenHeight = LocalRawScreenHeight.current BackHandler( enabled = isCustomizing, Loading Loading @@ -273,5 +292,11 @@ private fun SceneScope.QuickSettingsScene( modifier = Modifier.align(Alignment.CenterHorizontally), ) } NotificationScrollingStack( viewModel = notificationsPlaceholderViewModel, maxScrimTop = { screenHeight }, modifier = Modifier.fillMaxWidth().offset { IntOffset(x = 0, y = screenHeight.roundToInt()) }, ) } } packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt +8 −6 Original line number Diff line number Diff line package com.android.systemui.scene.ui.composable.transitions import androidx.compose.animation.core.tween import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TransitionBuilder import com.android.systemui.scene.shared.model.Scenes import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToQuickSettingsTransition() { spec = tween(durationMillis = 500) translate(Scenes.QuickSettings.rootElementKey, Edge.Top, true) fun TransitionBuilder.goneToQuickSettingsTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) toQuickSettingsTransition() } private val DefaultDuration = 500.milliseconds packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt +2 −19 Original line number Diff line number Diff line package com.android.systemui.scene.ui.composable.transitions import androidx.compose.animation.core.tween import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TransitionBuilder import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.ShadeHeader import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToShadeTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt()) fractionRange(start = .58f) { fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) fade(ShadeHeader.Elements.PrivacyChip) fade(QuickSettings.Elements.SplitShadeQuickSettings) fade(QuickSettings.Elements.FooterActions) } translate( QuickSettings.Elements.QuickQuickSettings, y = -ShadeHeader.Dimensions.CollapsedHeight * .66f ) translate(Notifications.Elements.NotificationScrim, Edge.Top, false) spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) toShadeTransition() } private val DefaultDuration = 500.milliseconds Loading
packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt +23 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,16 @@ package com.android.systemui.common.ui.compose.windowinsets import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import kotlinx.coroutines.flow.StateFlow Loading @@ -31,6 +36,9 @@ val LocalDisplayCutout = staticCompositionLocalOf { DisplayCutout() } /** The corner radius in px of the current display. */ val LocalScreenCornerRadius = staticCompositionLocalOf { 0.dp } /** The screen height in px without accounting for any screen insets (cutouts, status/nav bars) */ val LocalRawScreenHeight = staticCompositionLocalOf { 0f } @Composable fun ScreenDecorProvider( displayCutout: StateFlow<DisplayCutout>, Loading @@ -39,9 +47,23 @@ fun ScreenDecorProvider( ) { val cutout by displayCutout.collectAsState() val screenCornerRadiusDp = with(LocalDensity.current) { screenCornerRadius.toDp() } val density = LocalDensity.current val navBarHeight = with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding() val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding() val screenHeight = with(density) { (LocalConfiguration.current.screenHeightDp.dp + maxOf(statusBarHeight, displayCutoutHeight)) .toPx() } + navBarHeight CompositionLocalProvider( LocalScreenCornerRadius provides screenCornerRadiusDp, LocalDisplayCutout provides cutout LocalDisplayCutout provides cutout, LocalRawScreenHeight provides screenHeight, ) { content() } Loading
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +15 −15 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset Loading Loading @@ -57,7 +56,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.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp Loading @@ -67,15 +65,17 @@ import androidx.compose.ui.util.lerp import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.NestedScrollBehavior import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.SceneTransitionLayoutState import com.android.compose.modifiers.height import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.res.R 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.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 import kotlin.math.roundToInt Loading Loading @@ -168,14 +168,7 @@ fun SceneScope.NotificationScrollingStack( val navBarHeight = with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding() val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding() val screenHeight = with(density) { (LocalConfiguration.current.screenHeightDp.dp + maxOf(statusBarHeight, displayCutoutHeight)) .toPx() } + navBarHeight val screenHeight = LocalRawScreenHeight.current val stackHeight = viewModel.stackHeight.collectAsState() Loading Loading @@ -253,7 +246,7 @@ fun SceneScope.NotificationScrollingStack( scrimCornerRadius, screenCornerRadius, { expansionFraction }, layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) layoutState.isNotificationScrimTransitioning(), ) .let { scrimRounding.value.toRoundedCornerShape(it) } clip = true Loading Loading @@ -288,7 +281,7 @@ fun SceneScope.NotificationScrollingStack( Modifier.fillMaxSize() .graphicsLayer { alpha = if (layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade)) { if (layoutState.isNotificationScrimTransitioning()) { (expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f) } else 1f } Loading Loading @@ -425,7 +418,7 @@ private fun Modifier.debugBackground( this } fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { private fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { val topRadius = if (isTopRounded) radius else 0.dp val bottomRadius = if (isBottomRounded) radius else 0.dp return RoundedCornerShape( Loading @@ -436,6 +429,13 @@ fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape { ) } private fun SceneTransitionLayoutState.isNotificationScrimTransitioning(): Boolean { return isTransitioningBetween(Scenes.Gone, Scenes.Shade) || isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade) || isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) || isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings) } private const val TAG = "FlexiNotifs" private val DEBUG_STACK_COLOR = Color(1f, 0f, 0f, 0.2f) private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f) Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +26 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState Loading @@ -50,19 +51,23 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.CompositingStrategy import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.colorResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.TransitionState import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.notifications.ui.composable.NotificationScrollingStack import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel import com.android.systemui.res.R Loading @@ -72,10 +77,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.viewmodel.NotificationsPlaceholderViewModel import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager import com.android.systemui.statusbar.phone.StatusBarLocation import javax.inject.Inject import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn Loading @@ -87,6 +94,7 @@ class QuickSettingsScene constructor( @Application private val applicationScope: CoroutineScope, private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, Loading @@ -106,6 +114,7 @@ constructor( ) { QuickSettingsScene( viewModel = viewModel, notificationsPlaceholderViewModel = notificationsPlaceholderViewModel, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, Loading @@ -117,6 +126,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( viewModel: QuickSettingsSceneViewModel, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, statusBarIconController: StatusBarIconController, Loading @@ -135,8 +145,17 @@ private fun SceneScope.QuickSettingsScene( ) // TODO(b/280887232): implement the real UI. Box(modifier = modifier.fillMaxSize().graphicsLayer { alpha = contentAlpha }) { Box( modifier = modifier.fillMaxSize().graphicsLayer { // 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. compositingStrategy = CompositingStrategy.Offscreen alpha = contentAlpha } ) { val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState() val screenHeight = LocalRawScreenHeight.current BackHandler( enabled = isCustomizing, Loading Loading @@ -273,5 +292,11 @@ private fun SceneScope.QuickSettingsScene( modifier = Modifier.align(Alignment.CenterHorizontally), ) } NotificationScrollingStack( viewModel = notificationsPlaceholderViewModel, maxScrimTop = { screenHeight }, modifier = Modifier.fillMaxWidth().offset { IntOffset(x = 0, y = screenHeight.roundToInt()) }, ) } }
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt +8 −6 Original line number Diff line number Diff line package com.android.systemui.scene.ui.composable.transitions import androidx.compose.animation.core.tween import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TransitionBuilder import com.android.systemui.scene.shared.model.Scenes import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToQuickSettingsTransition() { spec = tween(durationMillis = 500) translate(Scenes.QuickSettings.rootElementKey, Edge.Top, true) fun TransitionBuilder.goneToQuickSettingsTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) toQuickSettingsTransition() } private val DefaultDuration = 500.milliseconds
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt +2 −19 Original line number Diff line number Diff line package com.android.systemui.scene.ui.composable.transitions import androidx.compose.animation.core.tween import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TransitionBuilder import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.ShadeHeader import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToShadeTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt()) fractionRange(start = .58f) { fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) fade(ShadeHeader.Elements.PrivacyChip) fade(QuickSettings.Elements.SplitShadeQuickSettings) fade(QuickSettings.Elements.FooterActions) } translate( QuickSettings.Elements.QuickQuickSettings, y = -ShadeHeader.Dimensions.CollapsedHeight * .66f ) translate(Notifications.Elements.NotificationScrim, Edge.Top, false) spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) toShadeTransition() } private val DefaultDuration = 500.milliseconds