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

Commit 9b676f52 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Make ElementKey in animateSharedXAsState optional

Bug: 298153892
Test: atest AnimatedSharedAsStateTest
Change-Id: I6a2cd258a54ea17b3ca4c1ccdcda7bd1bf6fba9a
parent c737d35e
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ import com.android.compose.ui.util.lerp
fun SceneScope.animateSharedIntAsState(
    value: Int,
    key: ValueKey,
    element: ElementKey,
    element: ElementKey?,
    canOverflow: Boolean = true,
): State<Int> {
    return animateSharedValueAsState(value, key, element, ::lerp, canOverflow)
@@ -65,7 +65,7 @@ fun MovableElementScope.animateSharedIntAsState(
fun SceneScope.animateSharedFloatAsState(
    value: Float,
    key: ValueKey,
    element: ElementKey,
    element: ElementKey?,
    canOverflow: Boolean = true,
): State<Float> {
    return animateSharedValueAsState(value, key, element, ::lerp, canOverflow)
@@ -94,7 +94,7 @@ fun MovableElementScope.animateSharedFloatAsState(
fun SceneScope.animateSharedDpAsState(
    value: Dp,
    key: ValueKey,
    element: ElementKey,
    element: ElementKey?,
    canOverflow: Boolean = true,
): State<Dp> {
    return animateSharedValueAsState(value, key, element, ::lerp, canOverflow)
@@ -123,7 +123,7 @@ fun MovableElementScope.animateSharedDpAsState(
fun SceneScope.animateSharedColorAsState(
    value: Color,
    key: ValueKey,
    element: ElementKey,
    element: ElementKey?,
): State<Color> {
    return animateSharedValueAsState(value, key, element, ::lerp, canOverflow = false)
}
@@ -145,7 +145,7 @@ fun MovableElementScope.animateSharedColorAsState(
internal fun <T> animateSharedValueAsState(
    layoutImpl: SceneTransitionLayoutImpl,
    scene: Scene,
    element: Element,
    element: Element?,
    key: ValueKey,
    value: T,
    lerp: (T, T, Float) -> T,
@@ -153,9 +153,9 @@ internal fun <T> animateSharedValueAsState(
): State<T> {
    val sharedValue =
        Snapshot.withoutReadObservation {
            element.sceneValues.getValue(scene.key).sharedValues.getOrPut(key) {
                Element.SharedValue(key, value)
            } as Element.SharedValue<T>
            val sharedValues =
                element?.sceneValues?.getValue(scene.key)?.sharedValues ?: scene.sharedValues
            sharedValues.getOrPut(key) { Element.SharedValue(key, value) } as Element.SharedValue<T>
        }

    if (value != sharedValue.value) {
@@ -169,7 +169,7 @@ internal fun <T> animateSharedValueAsState(

private fun <T> computeValue(
    layoutImpl: SceneTransitionLayoutImpl,
    element: Element,
    element: Element?,
    sharedValue: Element.SharedValue<T>,
    lerp: (T, T, Float) -> T,
    canOverflow: Boolean,
@@ -184,8 +184,14 @@ private fun <T> computeValue(
    }

    fun sceneValue(scene: SceneKey): Element.SharedValue<T>? {
        val sceneValues = element.sceneValues[scene] ?: return null
        val value = sceneValues.sharedValues[sharedValue.key] ?: return null
        val sharedValues =
            if (element == null) {
                layoutImpl.scene(scene).sharedValues
            } else {
                element.sceneValues[scene]?.sharedValues
            }
                ?: return null
        val value = sharedValues[sharedValue.key] ?: return null
        return value as Element.SharedValue<T>
    }

+12 −6
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.platform.testTag
@@ -44,6 +45,9 @@ internal class Scene(
    var zIndex by mutableFloatStateOf(zIndex)
    var size by mutableStateOf(IntSize.Zero)

    /** The shared values in this scene that are not tied to a specific element. */
    val sharedValues = SnapshotStateMap<ValueKey, Element.SharedValue<*>>()

    @Composable
    fun Content(modifier: Modifier = Modifier) {
        Box(modifier.zIndex(zIndex).onPlaced { size = it.size }.testTag(key.testTag)) {
@@ -69,16 +73,18 @@ private class SceneScopeImpl(
    override fun <T> animateSharedValueAsState(
        value: T,
        key: ValueKey,
        element: ElementKey,
        element: ElementKey?,
        lerp: (T, T, Float) -> T,
        canOverflow: Boolean
    ): State<T> {
        val element =
            layoutImpl.elements[element]
            element?.let { key ->
                layoutImpl.elements[key]
                    ?: error(
                    "Element $element is not composed. Make sure to call animateSharedXAsState " +
                        "Element $key is not composed. Make sure to call animateSharedXAsState " +
                            "*after* Modifier.element(key)."
                    )
            }

        return animateSharedValueAsState(
            layoutImpl,
+4 −2
Original line number Diff line number Diff line
@@ -142,7 +142,9 @@ interface SceneScope {
     *
     * @param value the value of this shared value in the current scene.
     * @param key the key of this shared value.
     * @param element the element associated with this value.
     * @param element the element associated with this value. If `null`, this value will be
     *   associated at the scene level, which means that [key] should be used maximum once in the
     *   same scene.
     * @param lerp the *linear* interpolation function that should be used to interpolate between
     *   two different values. Note that it has to be linear because the [fraction] passed to this
     *   interpolator is already interpolated.
@@ -157,7 +159,7 @@ interface SceneScope {
    fun <T> animateSharedValueAsState(
        value: T,
        key: ValueKey,
        element: ElementKey,
        element: ElementKey?,
        lerp: (start: T, stop: T, fraction: Float) -> T,
        canOverflow: Boolean,
    ): State<T>
+2 −1
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ class AnimatedSharedAsStateTest {
            val int by animateSharedIntAsState(targetValues.int, TestValues.Value1, key)
            val float by animateSharedFloatAsState(targetValues.float, TestValues.Value2, key)
            val dp by animateSharedDpAsState(targetValues.dp, TestValues.Value3, key)
            val color by animateSharedColorAsState(targetValues.color, TestValues.Value4, key)
            val color by
                animateSharedColorAsState(targetValues.color, TestValues.Value4, element = null)

            // Make sure we read the values during composition, so that we recompose and call
            // onCurrentValueChanged() with the latest values.