Loading packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +29 −9 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.viewinterop.AndroidView import com.android.compose.animation.scene.MovableElementKey import com.android.compose.animation.scene.SceneScope Loading @@ -51,6 +53,7 @@ fun SceneScope.MediaCarousel( mediaHost: MediaHost, modifier: Modifier = Modifier, carouselController: MediaCarouselController, offsetProvider: (() -> IntOffset)? = null, ) { if (!isVisible) { return Loading @@ -68,20 +71,37 @@ fun SceneScope.MediaCarousel( MovableElement( key = MediaCarousel.Elements.Content, modifier = modifier.height(mediaHeight).fillMaxWidth() modifier = modifier.height(mediaHeight).fillMaxWidth(), ) { content { AndroidView( modifier = Modifier.fillMaxSize().layout { measurable, constraints -> Modifier.fillMaxSize() .approachLayout( isMeasurementApproachInProgress = { offsetProvider != null }, approachMeasure = { measurable, constraints -> val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.placeRelative( offsetProvider?.invoke() ?: IntOffset.Zero ) } } ) .layout { measurable, constraints -> val placeable = measurable.measure(constraints) // Notify controller to size the carousel for the current space mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height) carouselController.setSceneContainerSize(placeable.width, placeable.height) carouselController.setSceneContainerSize( placeable.width, placeable.height ) layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } }, factory = { context -> FrameLayout(context).apply { Loading packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt +0 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.model.Scenes /** [ElementContentPicker] implementation for the media carousel object. */ object MediaContentPicker : StaticElementContentPicker { const val SHADE_FRACTION = 0.66f override val contents = setOf( Scenes.Lockscreen, Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt +0 −7 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ 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.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.composable.MediaContentPicker import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.Shade Loading Loading @@ -54,13 +53,7 @@ fun TransitionBuilder.goneToSplitShadeTransition( fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) } fractionRange(start = .33f) { val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION val qsExpansionDiff = ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation)) fade(MediaCarousel.Elements.Content) fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt +3 −7 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ 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.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.composable.MediaContentPicker import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.scene.shared.model.Scenes Loading Loading @@ -62,12 +61,9 @@ fun TransitionBuilder.toShadeTransition( fade(QuickSettings.Elements.FooterActions) } val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION val qsExpansionDiff = ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight translate(QuickSettings.Elements.QuickQuickSettings, y = -qsTranslation) translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation)) val qsTranslation = -ShadeHeader.Dimensions.CollapsedHeight * 0.66f translate(QuickSettings.Elements.QuickQuickSettings, y = qsTranslation) translate(MediaCarousel.Elements.Content, y = qsTranslation) translate(Notifications.Elements.NotificationScrim, Edge.Top, false) } Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeMediaOffsetProvider.kt 0 → 100644 +79 −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.shade.ui.composable import androidx.compose.ui.unit.IntOffset import com.android.systemui.qs.ui.adapter.QSSceneAdapter /** * Provider for the extra offset for the Media section in the shade to accommodate for the squishing * qs or qqs tiles. */ interface ShadeMediaOffsetProvider { /** Returns current offset to be applied to the Media Carousel */ val offset: IntOffset /** * [ShadeMediaOffsetProvider] implementation for Quick Settings. * * [updateLayout] should represent an access to some state to trigger Compose to relayout to * track [QSSceneAdapter] internal state changes during the transition. */ class Qs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) : ShadeMediaOffsetProvider { override val offset: IntOffset get() = calculateQsOffset( updateLayout, qsSceneAdapter.qsHeight, qsSceneAdapter.squishedQsHeight ) } /** * [ShadeMediaOffsetProvider] implementation for Quick Quick Settings. * * [updateLayout] should represent an access to some state to trigger Compose to relayout to * track [QSSceneAdapter] internal state changes during the transition. */ class Qqs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) : ShadeMediaOffsetProvider { override val offset: IntOffset get() = calculateQsOffset( updateLayout, qsSceneAdapter.qqsHeight, qsSceneAdapter.squishedQqsHeight ) } companion object { protected fun calculateQsOffset( updateLayout: () -> Unit, qsHeight: Int, qsSquishedHeight: Int ): IntOffset { updateLayout() val distanceFromBottomToActualBottom = qsHeight - qsSquishedHeight return IntOffset(0, -distanceFromBottomToActualBottom) } } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +29 −9 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.viewinterop.AndroidView import com.android.compose.animation.scene.MovableElementKey import com.android.compose.animation.scene.SceneScope Loading @@ -51,6 +53,7 @@ fun SceneScope.MediaCarousel( mediaHost: MediaHost, modifier: Modifier = Modifier, carouselController: MediaCarouselController, offsetProvider: (() -> IntOffset)? = null, ) { if (!isVisible) { return Loading @@ -68,20 +71,37 @@ fun SceneScope.MediaCarousel( MovableElement( key = MediaCarousel.Elements.Content, modifier = modifier.height(mediaHeight).fillMaxWidth() modifier = modifier.height(mediaHeight).fillMaxWidth(), ) { content { AndroidView( modifier = Modifier.fillMaxSize().layout { measurable, constraints -> Modifier.fillMaxSize() .approachLayout( isMeasurementApproachInProgress = { offsetProvider != null }, approachMeasure = { measurable, constraints -> val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.placeRelative( offsetProvider?.invoke() ?: IntOffset.Zero ) } } ) .layout { measurable, constraints -> val placeable = measurable.measure(constraints) // Notify controller to size the carousel for the current space mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height) carouselController.setSceneContainerSize(placeable.width, placeable.height) carouselController.setSceneContainerSize( placeable.width, placeable.height ) layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } }, factory = { context -> FrameLayout(context).apply { Loading
packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt +0 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.model.Scenes /** [ElementContentPicker] implementation for the media carousel object. */ object MediaContentPicker : StaticElementContentPicker { const val SHADE_FRACTION = 0.66f override val contents = setOf( Scenes.Lockscreen, Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt +0 −7 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ 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.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.composable.MediaContentPicker import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.shade.ui.composable.Shade Loading Loading @@ -54,13 +53,7 @@ fun TransitionBuilder.goneToSplitShadeTransition( fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) } fractionRange(start = .33f) { val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION val qsExpansionDiff = ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation)) fade(MediaCarousel.Elements.Content) fade(ShadeHeader.Elements.Clock) fade(ShadeHeader.Elements.CollapsedContentStart) fade(ShadeHeader.Elements.CollapsedContentEnd) Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt +3 −7 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ 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.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.composable.MediaContentPicker import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.scene.shared.model.Scenes Loading Loading @@ -62,12 +61,9 @@ fun TransitionBuilder.toShadeTransition( fade(QuickSettings.Elements.FooterActions) } val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION val qsExpansionDiff = ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight translate(QuickSettings.Elements.QuickQuickSettings, y = -qsTranslation) translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation)) val qsTranslation = -ShadeHeader.Dimensions.CollapsedHeight * 0.66f translate(QuickSettings.Elements.QuickQuickSettings, y = qsTranslation) translate(MediaCarousel.Elements.Content, y = qsTranslation) translate(Notifications.Elements.NotificationScrim, Edge.Top, false) } Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeMediaOffsetProvider.kt 0 → 100644 +79 −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.shade.ui.composable import androidx.compose.ui.unit.IntOffset import com.android.systemui.qs.ui.adapter.QSSceneAdapter /** * Provider for the extra offset for the Media section in the shade to accommodate for the squishing * qs or qqs tiles. */ interface ShadeMediaOffsetProvider { /** Returns current offset to be applied to the Media Carousel */ val offset: IntOffset /** * [ShadeMediaOffsetProvider] implementation for Quick Settings. * * [updateLayout] should represent an access to some state to trigger Compose to relayout to * track [QSSceneAdapter] internal state changes during the transition. */ class Qs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) : ShadeMediaOffsetProvider { override val offset: IntOffset get() = calculateQsOffset( updateLayout, qsSceneAdapter.qsHeight, qsSceneAdapter.squishedQsHeight ) } /** * [ShadeMediaOffsetProvider] implementation for Quick Quick Settings. * * [updateLayout] should represent an access to some state to trigger Compose to relayout to * track [QSSceneAdapter] internal state changes during the transition. */ class Qqs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) : ShadeMediaOffsetProvider { override val offset: IntOffset get() = calculateQsOffset( updateLayout, qsSceneAdapter.qqsHeight, qsSceneAdapter.squishedQqsHeight ) } companion object { protected fun calculateQsOffset( updateLayout: () -> Unit, qsHeight: Int, qsSquishedHeight: Int ): IntOffset { updateLayout() val distanceFromBottomToActualBottom = qsHeight - qsSquishedHeight return IntOffset(0, -distanceFromBottomToActualBottom) } } }