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

Commit f639aa65 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Introduce ElementStateScope

This CL introduces ElementStateScope, which is extended by both
SceneScope and UserActionDistance. This allows scenes to have custom
animation logic that depends on the target state of an element or scene.

Test: SwipeToSceneTest#dynamicSwipeDistance
Flag: N/A
Bug: 308961608
Change-Id: I313f8c0b57b7aa8a43f3c60ce6096536d2172893
parent 256a2727
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ internal class Scene(
internal class SceneScopeImpl(
    private val layoutImpl: SceneTransitionLayoutImpl,
    private val scene: Scene,
) : SceneScope {
) : SceneScope, ElementStateScope by layoutImpl.elementStateScope {
    override val layoutState: SceneTransitionLayoutState = layoutImpl.state

    override fun Modifier.element(key: ElementKey): Modifier {
+23 −20
Original line number Diff line number Diff line
@@ -131,9 +131,30 @@ interface SceneTransitionLayoutScope {
 */
@DslMarker annotation class ElementDsl

/** A scope that can be used to query the target state of an element or scene. */
interface ElementStateScope {
    /**
     * Return the *target* size of [this] element in the given [scene], i.e. the size of the element
     * when idle, or `null` if the element is not composed and measured in that scene (yet).
     */
    fun ElementKey.targetSize(scene: SceneKey): IntSize?

    /**
     * Return the *target* offset of [this] element in the given [scene], i.e. the size of the
     * element when idle, or `null` if the element is not composed and placed in that scene (yet).
     */
    fun ElementKey.targetOffset(scene: SceneKey): Offset?

    /**
     * Return the *target* size of [this] scene, i.e. the size of the scene when idle, or `null` if
     * the scene was never composed.
     */
    fun SceneKey.targetSize(): IntSize?
}

@Stable
@ElementDsl
interface BaseSceneScope {
interface BaseSceneScope : ElementStateScope {
    /** The state of the [SceneTransitionLayout] in which this scene is contained. */
    val layoutState: SceneTransitionLayoutState

@@ -415,25 +436,7 @@ interface UserActionDistance {
    ): Float
}

interface UserActionDistanceScope : Density {
    /**
     * Return the *target* size of [this] element in the given [scene], i.e. the size of the element
     * when idle, or `null` if the element is not composed and measured in that scene (yet).
     */
    fun ElementKey.targetSize(scene: SceneKey): IntSize?

    /**
     * Return the *target* offset of [this] element in the given [scene], i.e. the size of the
     * element when idle, or `null` if the element is not composed and placed in that scene (yet).
     */
    fun ElementKey.targetOffset(scene: SceneKey): Offset?

    /**
     * Return the *target* size of [this] scene, i.e. the size of the scene when idle, or `null` if
     * the scene was never composed.
     */
    fun SceneKey.targetSize(): IntSize?
}
interface UserActionDistanceScope : Density, ElementStateScope

/** The user action has a fixed [absoluteDistance]. */
class FixedDistance(private val distance: Dp) : UserActionDistance {
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ internal class SceneTransitionLayoutImpl(
    private val horizontalDraggableHandler: DraggableHandlerImpl
    private val verticalDraggableHandler: DraggableHandlerImpl

    internal val elementStateScope = ElementStateScopeImpl(this)
    private var _userActionDistanceScope: UserActionDistanceScope? = null
    internal val userActionDistanceScope: UserActionDistanceScope
        get() =
+12 −8
Original line number Diff line number Diff line
@@ -19,15 +19,9 @@ package com.android.compose.animation.scene
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.unit.IntSize

internal class UserActionDistanceScopeImpl(
internal class ElementStateScopeImpl(
    private val layoutImpl: SceneTransitionLayoutImpl,
) : UserActionDistanceScope {
    override val density: Float
        get() = layoutImpl.density.density

    override val fontScale: Float
        get() = layoutImpl.density.fontScale

) : ElementStateScope {
    override fun ElementKey.targetSize(scene: SceneKey): IntSize? {
        return layoutImpl.elements[this]?.sceneStates?.get(scene)?.targetSize.takeIf {
            it != Element.SizeUnspecified
@@ -44,3 +38,13 @@ internal class UserActionDistanceScopeImpl(
        return layoutImpl.scenes[this]?.targetSize.takeIf { it != IntSize.Zero }
    }
}

internal class UserActionDistanceScopeImpl(
    private val layoutImpl: SceneTransitionLayoutImpl,
) : UserActionDistanceScope, ElementStateScope by layoutImpl.elementStateScope {
    override val density: Float
        get() = layoutImpl.density.density

    override val fontScale: Float
        get() = layoutImpl.density.fontScale
}