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

Commit 62c483b1 authored by omarmt's avatar omarmt
Browse files

Do not draw elements that are not part of the transition

When transitioning between Transition, avoid drawing elements that are
not part of the new transition.

Test: atest ElementTest
Bug: 332586311
Flag: NA
Change-Id: I1afefb05d0324dbc9b39418b8d5e2507f310f6fa
parent 059ac2d1
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -261,16 +261,19 @@ private fun shouldDrawElement(
    scene: Scene,
    element: Element,
): Boolean {
    val transition = layoutImpl.state.currentTransition

    // Always draw the element if there is no ongoing transition or if the element is not shared or
    // if the current scene is the one that is currently over scrolling with [OverscrollSpec].
    if (
        transition == null ||
            transition.fromScene !in element.sceneStates ||
            transition.toScene !in element.sceneStates ||
            transition.currentOverscrollSpec?.scene == scene.key
    ) {
    val transition = layoutImpl.state.currentTransition ?: return true

    val inFromScene = transition.fromScene in element.sceneStates
    val inToScene = transition.toScene in element.sceneStates

    // If an element is not present in any scene, it should not be drawn.
    if (!inFromScene && !inToScene) {
        return false
    }

    // Always draw if the element is not shared or if the current scene is the one that is currently
    // over scrolling with [OverscrollSpec].
    if (!inFromScene || !inToScene || transition.currentOverscrollSpec?.scene == scene.key) {
        return true
    }

+55 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.layout.intermediateLayout
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
@@ -174,6 +175,60 @@ class ElementTest {
        }
    }

    @Test
    fun elementsNotInTransition_shouldNotBeDrawn() {
        val nFrames = 20
        val frameDuration = 16L
        val tween = tween<Float>(nFrames * frameDuration.toInt())
        val layoutSize = 100.dp
        val elementSize = 50.dp
        val elementOffset = 20.dp

        lateinit var changeScene: (SceneKey) -> Unit

        rule.testTransition(
            from = TestScenes.SceneA,
            to = TestScenes.SceneB,
            transitionLayout = { currentScene, onChangeScene ->
                changeScene = onChangeScene

                SceneTransitionLayout(
                    currentScene,
                    onChangeScene,
                    transitions {
                        from(TestScenes.SceneA, to = TestScenes.SceneB) { spec = tween }
                        from(TestScenes.SceneB, to = TestScenes.SceneC) { spec = tween }
                    },
                ) {
                    scene(TestScenes.SceneA) {
                        Box(Modifier.size(layoutSize)) {
                            // Transformed element
                            Element(
                                TestElements.Bar,
                                elementSize,
                                elementOffset,
                            )
                        }
                    }
                    scene(TestScenes.SceneB) { Box(Modifier.size(layoutSize)) }
                    scene(TestScenes.SceneC) { Box(Modifier.size(layoutSize)) }
                }
            },
        ) {
            // Start transition from SceneA to SceneB
            at(1 * frameDuration) {
                onElement(TestElements.Bar).assertExists()

                // Start transition from SceneB to SceneC
                changeScene(TestScenes.SceneC)
            }

            at(2 * frameDuration) { onElement(TestElements.Bar).assertIsNotDisplayed() }

            at(3 * frameDuration) { onElement(TestElements.Bar).assertDoesNotExist() }
        }
    }

    @Test
    fun onlyMovingElements_noLayout_onlyPlacement() {
        val nFrames = 20