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

Commit 461e3b43 authored by Andreas Miko's avatar Andreas Miko
Browse files

Fix disabled NestedSharedElements

Nested Element Transitions were enabled in the previous commit but
because there are now elements with the same key in multiple scenes
this was still buggy.

Bug: 376659778
Test: new test adjusted and passed
Flag: com.android.systemui.scene_container
Change-Id: Ib93887587b33352969cfe3de24080f54d6ceec63
parent df6c3ed2
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -1342,19 +1342,15 @@ private inline fun <T> computeValue(

    // The content for which we compute the transformation. Note that this is not necessarily
    // [currentContent] because [currentContent] could be a different content than the transition
    // fromContent or toContent during interruptions.
    // fromContent or toContent during interruptions or when a ancestor transition is running.
    val content: ContentKey
    // Get the transformed value, i.e. the target value at the beginning (for entering elements) or
    // end (for leaving elements) of the transition.
    val contentState: Element.State
    when {
        isSharedElement && currentContent == fromContent -> {
            content = fromContent
            contentState = fromState!!
        }
        isSharedElement && currentContent == toContent -> {
            content = toContent
            contentState = toState!!
        isSharedElement -> {
            content = currentContent
            contentState = currentContentState
        }
        isAncestorTransition(layoutImpl, transition) -> {
            if (
@@ -1545,6 +1541,8 @@ private inline fun <T> computeValue(
        when {
            content == toContent -> true
            content == fromContent -> false
            isAncestorTransition(layoutImpl, transition) ->
                isEnteringAncestorTransition(layoutImpl, transition)
            content == transition.currentScene -> toState == null
            else -> content == toContent
        }
@@ -1564,6 +1562,13 @@ private fun isAncestorTransition(
    }
}

private fun isEnteringAncestorTransition(
    layoutImpl: SceneTransitionLayoutImpl,
    transition: TransitionState.Transition
): Boolean {
    return layoutImpl.ancestors.fastAny { it.inContent == transition.toContent }
}

private inline fun <T> PropertyTransformation<T>.requireInterpolatedTransformation(
    element: Element,
    transition: TransitionState.Transition,
+8 −2
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ class NestedSharedElementTest {
        val NestedNestedSceneB = SceneKey("NestedNestedSceneB")
    }

    private val elementVariant1 = SharedElement(0.dp, 0.dp, 100.dp, 100.dp, Color.Red)
    private val elementVariant1 = SharedElement(100.dp, 100.dp, 100.dp, 100.dp, Color.Red)
    private val elementVariant2 = SharedElement(40.dp, 80.dp, 60.dp, 20.dp, Color.Blue)
    private val elementVariant3 = SharedElement(80.dp, 40.dp, 140.dp, 180.dp, Color.Yellow)
    private val elementVariant4 = SharedElement(120.dp, 240.dp, 20.dp, 140.dp, Color.Green)
@@ -223,7 +223,8 @@ class NestedSharedElementTest {
                // In SceneA, Foo leaves to the left edge.
                translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left, false)

                // We can't reference the element inside the NestedSTL as of today
                // In NestedSceneA, Foo comes in from the top edge.
                translate(TestElements.Foo.inScene(Scenes.NestedSceneA), Edge.Top, false)
            },
        ) {
            before { onElement(TestElements.Foo).assertElementVariant(elementVariant1) }
@@ -234,6 +235,11 @@ class NestedSharedElementTest {
                        elementVariant1.y,
                    )
                    .assertSizeIsEqualTo(elementVariant1.width, elementVariant1.height)
                onElement(TestElements.Foo, scene = Scenes.NestedSceneA)
                    .assertPositionInRootIsEqualTo(
                        elementVariant2.x,
                        interpolate(0.dp, elementVariant2.y),
                    )
            }
            after { onElement(TestElements.Foo).assertElementVariant(elementVariant2) }
        }
+31 −5
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ package com.android.compose.animation.scene.transformation

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertPositionInRootIsEqualTo
import androidx.compose.ui.test.junit4.createComposeRule
@@ -47,11 +49,21 @@ class SharedElementTest {
        rule.testTransition(
            fromSceneContent = {
                // Foo is at (10, 50) with a size of (20, 80).
                Box(Modifier.offset(10.dp, 50.dp).element(TestElements.Foo).size(20.dp, 80.dp))
                Box(
                    Modifier.offset(10.dp, 50.dp)
                        .element(TestElements.Foo)
                        .size(20.dp, 80.dp)
                        .background(Color.Red)
                )
            },
            toSceneContent = {
                // Foo is at (50, 70) with a size of (10, 40).
                Box(Modifier.offset(50.dp, 70.dp).element(TestElements.Foo).size(10.dp, 40.dp))
                Box(
                    Modifier.offset(50.dp, 70.dp)
                        .element(TestElements.Foo)
                        .size(10.dp, 40.dp)
                        .background(Color.Blue)
                )
            },
            transition = {
                spec = tween(16 * 4, easing = LinearEasing)
@@ -88,13 +100,23 @@ class SharedElementTest {
            fromSceneContent = {
                Box(Modifier.fillMaxSize()) {
                    // Foo is at (10, 50).
                    Box(Modifier.offset(10.dp, 50.dp).element(TestElements.Foo))
                    Box(
                        Modifier.offset(10.dp, 50.dp)
                            .element(TestElements.Foo)
                            .size(20.dp)
                            .background(Color.Red)
                    )
                }
            },
            toSceneContent = {
                Box(Modifier.fillMaxSize()) {
                    // Foo is at (50, 60).
                    Box(Modifier.offset(50.dp, 60.dp).element(TestElements.Foo))
                    Box(
                        Modifier.offset(50.dp, 60.dp)
                            .element(TestElements.Foo)
                            .size(20.dp)
                            .background(Color.Blue)
                    )
                }
            },
            transition = {
@@ -104,7 +126,11 @@ class SharedElementTest {
                sharedElement(TestElements.Foo, enabled = false)

                // In SceneA, Foo leaves to the left edge.
                translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left)
                translate(
                    TestElements.Foo.inScene(TestScenes.SceneA),
                    Edge.Left,
                    startsOutsideLayoutBounds = false,
                )

                // In SceneB, Foo comes from the bottom edge.
                translate(TestElements.Foo.inScene(TestScenes.SceneB), Edge.Bottom)