Loading packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +40 −35 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.systemui.media.controls.ui.composable import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable Loading @@ -26,7 +28,6 @@ import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.viewinterop.AndroidView import androidx.core.view.contains import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope import com.android.systemui.media.controls.ui.controller.MediaCarouselController Loading @@ -36,7 +37,8 @@ import com.android.systemui.util.animation.MeasurementInput private object MediaCarousel { object Elements { internal val Content = ElementKey("MediaCarouselContent") internal val Content = ElementKey(debugName = "MediaCarouselContent", scenePicker = MediaScenePicker) } } Loading @@ -61,26 +63,25 @@ fun SceneScope.MediaCarousel( mediaHost.measurementInput = MeasurementInput(layoutWidth, layoutHeight) carouselController.setSceneContainerSize(layoutWidth, layoutHeight) MovableElement( key = MediaCarousel.Elements.Content, modifier = modifier.height(mediaHeight).fillMaxWidth() ) { content { AndroidView( modifier = modifier .element(MediaCarousel.Elements.Content) .height(mediaHeight) .fillMaxWidth() .layout { measurable, constraints -> Modifier.fillMaxSize().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) mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height) carouselController.setSceneContainerSize(placeable.width, placeable.height) layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } }, factory = { context -> FrameLayout(context).apply { val mediaFrame = carouselController.mediaFrame (mediaFrame.parent as? ViewGroup)?.removeView(mediaFrame) addView(mediaFrame) layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, Loading @@ -88,13 +89,17 @@ fun SceneScope.MediaCarousel( ) } }, update = { if (it.contains(carouselController.mediaFrame)) { return@AndroidView } val mediaFrame = carouselController.mediaFrame (mediaFrame.parent as? ViewGroup)?.removeView(mediaFrame) it.addView(mediaFrame) }, update = { it.setView(carouselController.mediaFrame) }, onRelease = { it.removeAllViews() } ) } } } private fun ViewGroup.setView(view: View) { if (view.parent == this) { return } (view.parent as? ViewGroup)?.removeView(view) addView(view) } packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaScenePicker.kt 0 → 100644 +72 −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.media.controls.ui.composable import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.ElementScenePicker import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionState import com.android.systemui.scene.shared.model.Scenes /** [ElementScenePicker] implementation for the media carousel object. */ object MediaScenePicker : ElementScenePicker { private val shadeLockscreenFraction = 0.65f private val scenes = setOf( Scenes.Lockscreen, Scenes.Shade, Scenes.QuickSettings, Scenes.QuickSettingsShade, Scenes.Communal ) override fun sceneDuringTransition( element: ElementKey, transition: TransitionState.Transition, fromSceneZIndex: Float, toSceneZIndex: Float ): SceneKey? { return when { // TODO: 352052894 - update with the actual scene picking transition.isTransitioning(from = Scenes.Lockscreen, to = Scenes.Shade) -> { if (transition.progress < shadeLockscreenFraction) { Scenes.Lockscreen } else { Scenes.Shade } } // TODO: 345467290 - update with the actual scene picking transition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) -> { if (transition.progress < 1f - shadeLockscreenFraction) { Scenes.Shade } else { Scenes.Lockscreen } } // TODO: 345467290 - update with the actual scene picking transition.isTransitioningBetween(Scenes.QuickSettings, Scenes.Shade) -> { Scenes.QuickSettings } // TODO: 340216785 - update with the actual scene picking else -> pickSingleSceneIn(scenes, transition, element) } } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +40 −35 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.systemui.media.controls.ui.composable import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable Loading @@ -26,7 +28,6 @@ import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.viewinterop.AndroidView import androidx.core.view.contains import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope import com.android.systemui.media.controls.ui.controller.MediaCarouselController Loading @@ -36,7 +37,8 @@ import com.android.systemui.util.animation.MeasurementInput private object MediaCarousel { object Elements { internal val Content = ElementKey("MediaCarouselContent") internal val Content = ElementKey(debugName = "MediaCarouselContent", scenePicker = MediaScenePicker) } } Loading @@ -61,26 +63,25 @@ fun SceneScope.MediaCarousel( mediaHost.measurementInput = MeasurementInput(layoutWidth, layoutHeight) carouselController.setSceneContainerSize(layoutWidth, layoutHeight) MovableElement( key = MediaCarousel.Elements.Content, modifier = modifier.height(mediaHeight).fillMaxWidth() ) { content { AndroidView( modifier = modifier .element(MediaCarousel.Elements.Content) .height(mediaHeight) .fillMaxWidth() .layout { measurable, constraints -> Modifier.fillMaxSize().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) mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height) carouselController.setSceneContainerSize(placeable.width, placeable.height) layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } }, factory = { context -> FrameLayout(context).apply { val mediaFrame = carouselController.mediaFrame (mediaFrame.parent as? ViewGroup)?.removeView(mediaFrame) addView(mediaFrame) layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, Loading @@ -88,13 +89,17 @@ fun SceneScope.MediaCarousel( ) } }, update = { if (it.contains(carouselController.mediaFrame)) { return@AndroidView } val mediaFrame = carouselController.mediaFrame (mediaFrame.parent as? ViewGroup)?.removeView(mediaFrame) it.addView(mediaFrame) }, update = { it.setView(carouselController.mediaFrame) }, onRelease = { it.removeAllViews() } ) } } } private fun ViewGroup.setView(view: View) { if (view.parent == this) { return } (view.parent as? ViewGroup)?.removeView(view) addView(view) }
packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaScenePicker.kt 0 → 100644 +72 −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.media.controls.ui.composable import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.ElementScenePicker import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionState import com.android.systemui.scene.shared.model.Scenes /** [ElementScenePicker] implementation for the media carousel object. */ object MediaScenePicker : ElementScenePicker { private val shadeLockscreenFraction = 0.65f private val scenes = setOf( Scenes.Lockscreen, Scenes.Shade, Scenes.QuickSettings, Scenes.QuickSettingsShade, Scenes.Communal ) override fun sceneDuringTransition( element: ElementKey, transition: TransitionState.Transition, fromSceneZIndex: Float, toSceneZIndex: Float ): SceneKey? { return when { // TODO: 352052894 - update with the actual scene picking transition.isTransitioning(from = Scenes.Lockscreen, to = Scenes.Shade) -> { if (transition.progress < shadeLockscreenFraction) { Scenes.Lockscreen } else { Scenes.Shade } } // TODO: 345467290 - update with the actual scene picking transition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) -> { if (transition.progress < 1f - shadeLockscreenFraction) { Scenes.Shade } else { Scenes.Lockscreen } } // TODO: 345467290 - update with the actual scene picking transition.isTransitioningBetween(Scenes.QuickSettings, Scenes.Shade) -> { Scenes.QuickSettings } // TODO: 340216785 - update with the actual scene picking else -> pickSingleSceneIn(scenes, transition, element) } } }