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

Commit 263eeb2a authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Make ElementKey in animateSharedXAsState optional" into main

parents 94fb5cf2 9b676f52
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)) {
@@ -68,16 +72,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.