Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 213fa4ad authored by Omar Miatello's avatar Omar Miatello
Browse files

MM: Introduce MotionDriver for constraint-driven animations 2/x

This introduces `MotionDriver`, a new component designed to act as a
central manager for driving mechanic-based animations within Compose
hierarchy.

Children now can:
1. Look up the `MotionDriver` from the modifier chain.
2. Request an animated value from it.
3. Supply a reactive `MotionSpec` that defines the animation's behavior.

Test: Tested on the previous MotionValueTests
Bug: 439598401
Flag: com.android.systemui.scene_container
Change-Id: I00f2942c846363c820d43bff24564c86545e2cf6
parent 6ebbf65b
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.mechanics.TileRevealFlag
import com.android.compose.lifecycle.LaunchedEffectWithLifecycle
import com.android.compose.lifecycle.LaunchedEffectWithLifecycle
import com.android.compose.modifiers.thenIf
import com.android.compose.modifiers.thenIf
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
@@ -392,6 +393,7 @@ private fun ContentScope.QuickSettingsLayout(
            TileGrid(
            TileGrid(
                viewModel = qsContainerViewModel.tileGridViewModel,
                viewModel = qsContainerViewModel.tileGridViewModel,
                modifier = Modifier.fillMaxWidth(),
                modifier = Modifier.fillMaxWidth(),
                enableRevealEffect = TileRevealFlag.isEnabled,
            )
            )


            // TODO(b/428805936): Double check this padding.
            // TODO(b/428805936): Double check this padding.
+5 −0
Original line number Original line Diff line number Diff line
@@ -51,10 +51,13 @@ import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.mechanics.TileRevealFlag
import com.android.compose.animation.scene.mechanics.rememberGestureContext
import com.android.compose.modifiers.thenIf
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.mechanics.behavior.VerticalExpandContainerSpec
import com.android.mechanics.behavior.VerticalExpandContainerSpec
import com.android.mechanics.behavior.verticalExpandContainerBackground
import com.android.mechanics.behavior.verticalExpandContainerBackground
import com.android.mechanics.compose.modifier.motionDriver
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.shade.ui.ShadeColors.shadePanel
import com.android.systemui.shade.ui.ShadeColors.shadePanel
import com.android.systemui.shade.ui.ShadeColors.shadePanelScrimBehind
import com.android.systemui.shade.ui.ShadeColors.shadePanelScrimBehind
@@ -86,12 +89,14 @@ fun ContentScope.OverlayShade(
                Modifier.fillMaxSize().panelContainerPadding(isFullWidth, alignmentOnWideScreens),
                Modifier.fillMaxSize().panelContainerPadding(isFullWidth, alignmentOnWideScreens),
            contentAlignment = if (isFullWidth) Alignment.TopCenter else alignmentOnWideScreens,
            contentAlignment = if (isFullWidth) Alignment.TopCenter else alignmentOnWideScreens,
        ) {
        ) {
            val gestureContext = rememberGestureContext()
            Panel(
            Panel(
                enableTransparency = enableTransparency,
                enableTransparency = enableTransparency,
                spec = panelSpec,
                spec = panelSpec,
                modifier =
                modifier =
                    Modifier.overscroll(verticalOverscrollEffect)
                    Modifier.overscroll(verticalOverscrollEffect)
                        .element(panelElement)
                        .element(panelElement)
                        .thenIf(TileRevealFlag.isEnabled) { Modifier.motionDriver(gestureContext) }
                        .panelWidth(isFullWidth)
                        .panelWidth(isFullWidth)
                        .onPlaced { coordinates ->
                        .onPlaced { coordinates ->
                            val bounds = coordinates.boundsInWindow()
                            val bounds = coordinates.boundsInWindow()
+12 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.compose.animation.scene.mechanics
package com.android.compose.animation.scene.mechanics


import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.mechanics.GestureContext
import com.android.mechanics.GestureContext
@@ -41,3 +43,13 @@ fun ContentScope.gestureContextOrDefault(
            get() = layoutState.currentTransition?.gestureContext
            get() = layoutState.currentTransition?.gestureContext
    }
    }
}
}

@Composable
fun ContentScope.rememberGestureContext(
    defaultDragOffset: Float = 0f,
    defaultDirection: InputDirection = InputDirection.Max,
): GestureContext {
    return remember(defaultDragOffset, defaultDirection) {
        gestureContextOrDefault(defaultDragOffset, defaultDirection)
    }
}
+2 −5
Original line number Original line Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.qs.panels.ui.compose
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.PaginatableViewModel
import com.android.systemui.qs.panels.ui.viewmodel.PaginatableViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
@@ -33,16 +32,14 @@ interface GridLayout {
     *
     *
     * @param listening can be used to compose the grid but limit when tiles should be listening. It
     * @param listening can be used to compose the grid but limit when tiles should be listening. It
     *   should be a function tracking a snapshot state.
     *   should be a function tracking a snapshot state.
     * @param revealEffectContainer The [ElementKey] of the container driving the reveal animation.
     * @param enableRevealEffect If `true`, the tiles will animate using the reveal animation.
     *   During expansion, tiles use this container's height to compute their own, creating a
     *   synchronized reveal effect. When `null`, the effect is disabled.
     */
     */
    @Composable
    @Composable
    fun ContentScope.TileGrid(
    fun ContentScope.TileGrid(
        tiles: List<TileViewModel>,
        tiles: List<TileViewModel>,
        modifier: Modifier,
        modifier: Modifier,
        listening: () -> Boolean,
        listening: () -> Boolean,
        revealEffectContainer: ElementKey?,
        enableRevealEffect: Boolean,
    )
    )


    @Composable
    @Composable
+2 −3
Original line number Original line Diff line number Diff line
@@ -40,7 +40,6 @@ import androidx.compose.ui.res.integerResource
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.padding
import com.android.compose.modifiers.padding
import com.android.systemui.common.ui.compose.PagerDots
import com.android.systemui.common.ui.compose.PagerDots
@@ -70,7 +69,7 @@ constructor(
        tiles: List<TileViewModel>,
        tiles: List<TileViewModel>,
        modifier: Modifier,
        modifier: Modifier,
        listening: () -> Boolean,
        listening: () -> Boolean,
        revealEffectContainer: ElementKey?,
        enableRevealEffect: Boolean,
    ) {
    ) {
        val viewModel =
        val viewModel =
            rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") {
            rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") {
@@ -147,7 +146,7 @@ constructor(
                        tiles = page,
                        tiles = page,
                        modifier = Modifier,
                        modifier = Modifier,
                        listening = listening,
                        listening = listening,
                        revealEffectContainer = null,
                        enableRevealEffect = false,
                    )
                    )
                }
                }
            }
            }
Loading