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

Commit fac45418 authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

Respect animationSpec for predictive back transition in STL

Bug: 350705972
Test: PredictiveBackHandlerTest
Flag: com.android.systemui.scene_container
Change-Id: Idba16d69d1da2892a0799b237506d4b1e353e48a
parent e4c655c5
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -126,7 +126,16 @@ private class PredictiveBackTransition(
        return coroutineScope
            .launch(start = CoroutineStart.ATOMIC) {
                try {
                    if (currentScene == toScene) {
                        animatable.animateTo(targetProgress, transformationSpec.progressSpec)
                    } else {
                        // If the back gesture is cancelled, the progress is animated back to 0f by
                        // the system. But we need this animate call anyways because
                        // PredictiveBackHandler doesn't guarantee that it ends at 0f. Since the
                        // remaining change in progress is usually very small, the progressSpec is
                        // omitted and the default spring spec used instead.
                        animatable.animateTo(targetProgress)
                    }
                } finally {
                    state.finishTransition(this@PredictiveBackTransition, scene)
                }
+34 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.compose.animation.scene

import androidx.activity.BackEventCompat
import androidx.activity.ComponentActivity
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.rememberCoroutineScope
@@ -59,7 +61,23 @@ class PredictiveBackHandlerTest {

    @Test
    fun testPredictiveBack() {
        val layoutState = rule.runOnUiThread { MutableSceneTransitionLayoutState(SceneA) }
        val transitionFrames = 2
        val layoutState =
            rule.runOnUiThread {
                MutableSceneTransitionLayoutState(
                    SceneA,
                    transitions =
                        transitions {
                            from(SceneA, to = SceneB) {
                                spec =
                                    tween(
                                        durationMillis = transitionFrames * 16,
                                        easing = LinearEasing
                                    )
                            }
                        }
                )
            }
        rule.setContent {
            SceneTransitionLayout(layoutState) {
                scene(SceneA, mapOf(Back to SceneB)) { Box(Modifier.fillMaxSize()) }
@@ -88,12 +106,27 @@ class PredictiveBackHandlerTest {
        assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
        assertThat(layoutState.transitionState).isIdle()

        rule.mainClock.autoAdvance = false

        // Start again and commit it.
        rule.runOnUiThread {
            dispatcher.dispatchOnBackStarted(backEvent())
            dispatcher.dispatchOnBackProgressed(backEvent(progress = 0.4f))
            dispatcher.onBackPressed()
        }
        rule.mainClock.advanceTimeByFrame()
        rule.waitForIdle()
        val transition2 = assertThat(layoutState.transitionState).isTransition()
        // verify that transition picks up progress from preview
        assertThat(transition2).hasProgress(0.4f, tolerance = 0.0001f)

        rule.mainClock.advanceTimeByFrame()
        rule.waitForIdle()
        // verify that transition is half way between preview-end-state (0.4f) and target-state (1f)
        // after one frame
        assertThat(transition2).hasProgress(0.7f, tolerance = 0.0001f)

        rule.mainClock.autoAdvance = true
        rule.waitForIdle()
        assertThat(layoutState.transitionState).hasCurrentScene(SceneB)
        assertThat(layoutState.transitionState).isIdle()