Loading packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ data class DisplayCutout( val viewDisplayCutoutKeyguardStatusBarView: ViewDisplayCutout? = null, ) { fun width() = abs(right.value - left.value).dp fun height() = abs(bottom.value - top.value).dp } enum class CutoutLocation { Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +0 −1 Original line number Diff line number Diff line Loading @@ -320,7 +320,6 @@ private fun SceneScope.QuickSettingsScene( createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, modifier = Modifier.padding(horizontal = 16.dp), ) } Spacer(modifier = Modifier.height(16.dp)) Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt +14 −0 Original line number Diff line number Diff line Loading @@ -5,10 +5,13 @@ import com.android.compose.animation.scene.transitions import com.android.systemui.bouncer.ui.composable.Bouncer import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.TransitionKeys.CollapseShadeInstantly import com.android.systemui.scene.shared.model.TransitionKeys.GoneToSplitShade import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToBouncerTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToCommunalTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToGoneTransition Loading @@ -35,6 +38,13 @@ val SceneContainerTransitions = transitions { from(Scenes.Bouncer, to = Scenes.Gone) { bouncerToGoneTransition() } from(Scenes.Gone, to = Scenes.Shade) { goneToShadeTransition() } from( Scenes.Gone, to = Scenes.Shade, key = GoneToSplitShade, ) { goneToSplitShadeTransition() } from( Scenes.Gone, to = Scenes.Shade, Loading Loading @@ -68,5 +78,9 @@ val SceneContainerTransitions = transitions { Notifications.Elements.NotificationScrim, y = { Shade.Dimensions.ScrimOverscrollLimit } ) translate( Shade.Elements.SplitShadeStartColumn, y = { Shade.Dimensions.ScrimOverscrollLimit } ) } } packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt 0 → 100644 +65 −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.scene.ui.composable.transitions import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.unit.IntSize import com.android.compose.animation.scene.TransitionBuilder import com.android.compose.animation.scene.UserActionDistance import com.android.compose.animation.scene.UserActionDistanceScope import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.shade.ui.composable.ShadeHeader import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToSplitShadeTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) swipeSpec = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold, ) distance = object : UserActionDistance { override fun UserActionDistanceScope.absoluteDistance( fromSceneSize: IntSize, orientation: Orientation, ): Float { return fromSceneSize.height.toFloat() * 2 / 3f } } fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) } fractionRange(start = .33f) { fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) fade(ShadeHeader.Elements.PrivacyChip) fade(QuickSettings.Elements.SplitShadeQuickSettings) fade(QuickSettings.Elements.FooterActions) fade(Notifications.Elements.NotificationScrim) } } private val DefaultDuration = 500.milliseconds packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +21 −5 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max import androidx.compose.ui.viewinterop.AndroidView import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexScenePicker Loading @@ -63,6 +64,7 @@ import com.android.systemui.battery.BatteryMeterView 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.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.res.R Loading @@ -77,6 +79,7 @@ import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel import com.android.systemui.statusbar.policy.Clock import kotlin.math.max object ShadeHeader { object Elements { Loading Loading @@ -121,7 +124,11 @@ fun SceneScope.CollapsedShadeHeader( } val cutoutWidth = LocalDisplayCutout.current.width() val cutoutHeight = LocalDisplayCutout.current.height() val cutoutTop = LocalDisplayCutout.current.top val cutoutLocation = LocalDisplayCutout.current.location val horizontalPadding = max(LocalScreenCornerRadius.current / 2f, Shade.Dimensions.HorizontalPadding) val useExpandedFormat by remember(cutoutLocation) { Loading @@ -140,7 +147,7 @@ fun SceneScope.CollapsedShadeHeader( contents = listOf( { Row { Row(modifier = Modifier.padding(horizontal = horizontalPadding)) { Clock( scale = 1f, viewModel = viewModel, Loading @@ -157,7 +164,12 @@ fun SceneScope.CollapsedShadeHeader( }, { if (isPrivacyChipVisible) { Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) { Box( modifier = Modifier.height(CollapsedHeight) .fillMaxWidth() .padding(horizontal = horizontalPadding) ) { PrivacyChip( viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd), Loading @@ -166,9 +178,13 @@ fun SceneScope.CollapsedShadeHeader( } else { Row( horizontalArrangement = Arrangement.End, modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) .padding(horizontal = horizontalPadding) ) { SystemIconContainer( modifier = Modifier.align(Alignment.CenterVertically) ) { SystemIconContainer { when (LocalWindowSizeClass.current.widthSizeClass) { WindowWidthSizeClass.Medium, WindowWidthSizeClass.Expanded -> Loading Loading @@ -206,7 +222,7 @@ fun SceneScope.CollapsedShadeHeader( val screenWidth = constraints.maxWidth val cutoutWidthPx = cutoutWidth.roundToPx() val height = CollapsedHeight.roundToPx() val height = max(cutoutHeight + (cutoutTop * 2), CollapsedHeight).roundToPx() val childConstraints = Constraints.fixed((screenWidth - cutoutWidthPx) / 2, height) val startMeasurable = measurables[0][0] Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ data class DisplayCutout( val viewDisplayCutoutKeyguardStatusBarView: ViewDisplayCutout? = null, ) { fun width() = abs(right.value - left.value).dp fun height() = abs(bottom.value - top.value).dp } enum class CutoutLocation { Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +0 −1 Original line number Diff line number Diff line Loading @@ -320,7 +320,6 @@ private fun SceneScope.QuickSettingsScene( createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, modifier = Modifier.padding(horizontal = 16.dp), ) } Spacer(modifier = Modifier.height(16.dp)) Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt +14 −0 Original line number Diff line number Diff line Loading @@ -5,10 +5,13 @@ import com.android.compose.animation.scene.transitions import com.android.systemui.bouncer.ui.composable.Bouncer import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.TransitionKeys.CollapseShadeInstantly import com.android.systemui.scene.shared.model.TransitionKeys.GoneToSplitShade import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToBouncerTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToCommunalTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToGoneTransition Loading @@ -35,6 +38,13 @@ val SceneContainerTransitions = transitions { from(Scenes.Bouncer, to = Scenes.Gone) { bouncerToGoneTransition() } from(Scenes.Gone, to = Scenes.Shade) { goneToShadeTransition() } from( Scenes.Gone, to = Scenes.Shade, key = GoneToSplitShade, ) { goneToSplitShadeTransition() } from( Scenes.Gone, to = Scenes.Shade, Loading Loading @@ -68,5 +78,9 @@ val SceneContainerTransitions = transitions { Notifications.Elements.NotificationScrim, y = { Shade.Dimensions.ScrimOverscrollLimit } ) translate( Shade.Elements.SplitShadeStartColumn, y = { Shade.Dimensions.ScrimOverscrollLimit } ) } }
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt 0 → 100644 +65 −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.scene.ui.composable.transitions import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.unit.IntSize import com.android.compose.animation.scene.TransitionBuilder import com.android.compose.animation.scene.UserActionDistance import com.android.compose.animation.scene.UserActionDistanceScope import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.shade.ui.composable.ShadeHeader import kotlin.time.Duration.Companion.milliseconds fun TransitionBuilder.goneToSplitShadeTransition( durationScale: Double = 1.0, ) { spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) swipeSpec = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold, ) distance = object : UserActionDistance { override fun UserActionDistanceScope.absoluteDistance( fromSceneSize: IntSize, orientation: Orientation, ): Float { return fromSceneSize.height.toFloat() * 2 / 3f } } fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) } fractionRange(start = .33f) { fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) fade(ShadeHeader.Elements.PrivacyChip) fade(QuickSettings.Elements.SplitShadeQuickSettings) fade(QuickSettings.Elements.FooterActions) fade(Notifications.Elements.NotificationScrim) } } private val DefaultDuration = 500.milliseconds
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +21 −5 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max import androidx.compose.ui.viewinterop.AndroidView import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexScenePicker Loading @@ -63,6 +64,7 @@ import com.android.systemui.battery.BatteryMeterView 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.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.res.R Loading @@ -77,6 +79,7 @@ import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel import com.android.systemui.statusbar.policy.Clock import kotlin.math.max object ShadeHeader { object Elements { Loading Loading @@ -121,7 +124,11 @@ fun SceneScope.CollapsedShadeHeader( } val cutoutWidth = LocalDisplayCutout.current.width() val cutoutHeight = LocalDisplayCutout.current.height() val cutoutTop = LocalDisplayCutout.current.top val cutoutLocation = LocalDisplayCutout.current.location val horizontalPadding = max(LocalScreenCornerRadius.current / 2f, Shade.Dimensions.HorizontalPadding) val useExpandedFormat by remember(cutoutLocation) { Loading @@ -140,7 +147,7 @@ fun SceneScope.CollapsedShadeHeader( contents = listOf( { Row { Row(modifier = Modifier.padding(horizontal = horizontalPadding)) { Clock( scale = 1f, viewModel = viewModel, Loading @@ -157,7 +164,12 @@ fun SceneScope.CollapsedShadeHeader( }, { if (isPrivacyChipVisible) { Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) { Box( modifier = Modifier.height(CollapsedHeight) .fillMaxWidth() .padding(horizontal = horizontalPadding) ) { PrivacyChip( viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd), Loading @@ -166,9 +178,13 @@ fun SceneScope.CollapsedShadeHeader( } else { Row( horizontalArrangement = Arrangement.End, modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) .padding(horizontal = horizontalPadding) ) { SystemIconContainer( modifier = Modifier.align(Alignment.CenterVertically) ) { SystemIconContainer { when (LocalWindowSizeClass.current.widthSizeClass) { WindowWidthSizeClass.Medium, WindowWidthSizeClass.Expanded -> Loading Loading @@ -206,7 +222,7 @@ fun SceneScope.CollapsedShadeHeader( val screenWidth = constraints.maxWidth val cutoutWidthPx = cutoutWidth.roundToPx() val height = CollapsedHeight.roundToPx() val height = max(cutoutHeight + (cutoutTop * 2), CollapsedHeight).roundToPx() val childConstraints = Constraints.fixed((screenWidth - cutoutWidthPx) / 2, height) val startMeasurable = measurables[0][0] Loading