diff options
8 files changed, 58 insertions, 61 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt index 48a348b9d1c5..c2dd80375d5a 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt @@ -109,8 +109,7 @@ internal fun CoroutineScope.animateToScene( layoutState.transitions.interruptionHandler.onInterruption( transitionState, target, - ) - ?: DefaultInterruptionHandler.onInterruption(transitionState, target) + ) ?: DefaultInterruptionHandler.onInterruption(transitionState, target) val animateFrom = interruptionResult.animateFrom if ( @@ -159,6 +158,7 @@ private fun CoroutineScope.animate( val transition = if (reversed) { OneOffTransition( + key = transitionKey, fromScene = targetScene, toScene = fromScene, currentScene = targetScene, @@ -167,6 +167,7 @@ private fun CoroutineScope.animate( ) } else { OneOffTransition( + key = transitionKey, fromScene = fromScene, toScene = targetScene, currentScene = targetScene, @@ -178,7 +179,7 @@ private fun CoroutineScope.animate( // Change the current layout state to start this new transition. This will compute the // TransformationSpec associated to this transition, which we need to initialize the Animatable // that will actually animate it. - layoutState.startTransition(transition, transitionKey, chain) + layoutState.startTransition(transition, chain) // The transition now contains the transformation spec that we should use to instantiate the // Animatable. @@ -207,6 +208,7 @@ private fun CoroutineScope.animate( } private class OneOffTransition( + override val key: TransitionKey?, fromScene: SceneKey, toScene: SceneKey, override val currentScene: SceneKey, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt index e9633c2f6603..60d78feec8c2 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt @@ -257,7 +257,7 @@ private class DragControllerImpl( fun updateTransition(newTransition: SwipeTransition, force: Boolean = false) { if (isDrivingTransition || force) { - layoutState.startTransition(newTransition, newTransition.key) + layoutState.startTransition(newTransition) } swipeTransition = newTransition @@ -555,7 +555,7 @@ private class SwipeTransition( val layoutImpl: SceneTransitionLayoutImpl, val layoutState: BaseSceneTransitionLayoutState, val coroutineScope: CoroutineScope, - val key: TransitionKey?, + override val key: TransitionKey?, val _fromScene: Scene, val _toScene: Scene, val userActionDistanceScope: UserActionDistanceScope, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt index 44affd968513..6a178c8b0c25 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt @@ -226,6 +226,12 @@ sealed interface TransitionState { val toScene: SceneKey, ) : TransitionState { /** + * The key of this transition. This should usually be null, but it can be specified to use a + * specific set of transformations associated to this transition. + */ + open val key: TransitionKey? = null + + /** * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or * when flinging quickly during a swipe gesture. @@ -455,11 +461,7 @@ internal abstract class BaseSceneTransitionLayoutState( * * Important: you *must* call [finishTransition] once the transition is finished. */ - internal fun startTransition( - transition: TransitionState.Transition, - transitionKey: TransitionKey? = null, - chain: Boolean = true, - ) { + internal fun startTransition(transition: TransitionState.Transition, chain: Boolean = true) { checkThread() // Compute the [TransformationSpec] when the transition starts. @@ -469,7 +471,9 @@ internal abstract class BaseSceneTransitionLayoutState( // Update the transition specs. transition.transformationSpec = - transitions.transitionSpec(fromScene, toScene, key = transitionKey).transformationSpec() + transitions + .transitionSpec(fromScene, toScene, key = transition.key) + .transformationSpec() if (orientation != null) { transition.updateOverscrollSpecs( fromSpec = transitions.overscrollSpec(fromScene, orientation), @@ -568,9 +572,10 @@ internal abstract class BaseSceneTransitionLayoutState( originalTransition = transitionState, fromScene = targetCurrentScene, toScene = matchingLink.targetTo, + key = matchingLink.targetTransitionKey, ) - stateLink.target.startTransition(linkedTransition, matchingLink.targetTransitionKey) + stateLink.target.startTransition(linkedTransition) activeTransitionLinks[stateLink] = linkedTransition } } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt index 79f126d24561..ed9888560f05 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt @@ -17,6 +17,7 @@ package com.android.compose.animation.scene.transition.link import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.TransitionKey import com.android.compose.animation.scene.TransitionState import kotlinx.coroutines.Job @@ -25,6 +26,7 @@ internal class LinkedTransition( private val originalTransition: TransitionState.Transition, fromScene: SceneKey, toScene: SceneKey, + override val key: TransitionKey? = null, ) : TransitionState.Transition(fromScene, toScene) { override val currentScene: SceneKey diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt index 7827d85bcfb0..41cacb4c71fc 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt @@ -638,10 +638,7 @@ class ElementTest { // Change the current transition. rule.runOnUiThread { - state.startTransition( - transition(from = SceneA, to = SceneB, progress = { 0.5f }), - transitionKey = null, - ) + state.startTransition(transition(from = SceneA, to = SceneB, progress = { 0.5f })) } // The size of Foo should still be 20dp given that the new state was not composed yet. @@ -1170,7 +1167,7 @@ class ElementTest { val offsetInAToB = lerp(offsetInA, offsetInB, aToBProgress) val sizeInAToB = lerp(sizeInA, sizeInB, aToBProgress) val valueInAToB = lerp(valueInA, valueInB, aToBProgress) - rule.runOnUiThread { state.startTransition(aToB, transitionKey = null) } + rule.runOnUiThread { state.startTransition(aToB) } rule .onNode(isElement(TestElements.Foo, SceneB)) .assertSizeIsEqualTo(sizeInAToB) @@ -1190,7 +1187,7 @@ class ElementTest { progress = { bToCProgress }, interruptionProgress = { interruptionProgress }, ) - rule.runOnUiThread { state.startTransition(bToC, transitionKey = null) } + rule.runOnUiThread { state.startTransition(bToC) } // The interruption deltas, which will be multiplied by the interruption progress then added // to the current transition offset and size. @@ -1332,9 +1329,9 @@ class ElementTest { interruptionProgress = { bToCInterruptionProgress }, onFinish = neverFinish(), ) - rule.runOnUiThread { state.startTransition(aToB, transitionKey = null) } + rule.runOnUiThread { state.startTransition(aToB) } rule.waitForIdle() - rule.runOnUiThread { state.startTransition(bToC, transitionKey = null) } + rule.runOnUiThread { state.startTransition(bToC) } // Foo is placed in both B and C given that the shared transition is disabled. In B, its // offset is impacted by the interruption but in C it is not. @@ -1370,7 +1367,7 @@ class ElementTest { progress = { 0.7f }, interruptionProgress = { 1f }, ) - rule.runOnUiThread { state.startTransition(bToA, transitionKey = null) } + rule.runOnUiThread { state.startTransition(bToA) } // Foo should have the position it had in B right before the interruption. rule @@ -1394,8 +1391,7 @@ class ElementTest { to = SceneB, progress = { -1f }, orientation = Orientation.Horizontal - ), - transitionKey = null, + ) ) } } @@ -1512,8 +1508,7 @@ class ElementTest { to = SceneB, progress = { 0.6f }, interruptionProgress = { interruptionProgress }, - ), - transitionKey = null + ) ) } rule.waitForIdle() diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt index 85d4165b4bf6..09d1a827d0c7 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt @@ -40,7 +40,7 @@ class InterruptionHandlerTest { val state = MutableSceneTransitionLayoutState( SceneA, - transitions { /* default interruption handler */}, + transitions { /* default interruption handler */ }, ) state.setTargetScene(SceneB, coroutineScope = this) @@ -160,7 +160,7 @@ class InterruptionHandlerTest { progressVelocity = { progressVelocity }, onFinish = { launch {} }, ) - state.startTransition(aToB, transitionKey = null) + state.startTransition(aToB) // Animate back to A. The previous transition is reversed, i.e. it has the same (from, to) // pair, and its velocity is used when animating the progress back to 0. @@ -186,7 +186,7 @@ class InterruptionHandlerTest { progressVelocity = { progressVelocity }, onFinish = { launch {} }, ) - state.startTransition(aToB, transitionKey = null) + state.startTransition(aToB) // Animate to B. The previous transition is reversed, i.e. it has the same (from, to) pair, // and its velocity is used when animating the progress to 1. diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt index 2a75e13066df..55431354b693 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt @@ -135,7 +135,7 @@ class ObservableTransitionStateTest { var transitionCurrentScene by mutableStateOf(SceneA) val transition = transition(from = SceneA, to = SceneB, current = { transitionCurrentScene }) - state.startTransition(transition, transitionKey = null) + state.startTransition(transition) assertThat(currentScene.value).isEqualTo(SceneA) // Change the transition current scene. diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt index d2c8bd6928ee..de6f1cc518f4 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt @@ -57,7 +57,7 @@ class SceneTransitionLayoutStateTest { @Test fun isTransitioningTo_transition() { val state = MutableSceneTransitionLayoutStateImpl(SceneA, SceneTransitions.Empty) - state.startTransition(transition(from = SceneA, to = SceneB), transitionKey = null) + state.startTransition(transition(from = SceneA, to = SceneB)) assertThat(state.isTransitioning()).isTrue() assertThat(state.isTransitioning(from = SceneA)).isTrue() @@ -175,7 +175,7 @@ class SceneTransitionLayoutStateTest { val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() @@ -211,7 +211,7 @@ class SceneTransitionLayoutStateTest { val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() assertThat(parentParentState.isTransitioning(SceneB, SceneC)).isTrue() @@ -229,7 +229,7 @@ class SceneTransitionLayoutStateTest { var progress = 0f val childTransition = transition(SceneA, SceneB, progress = { progress }) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(parentState.currentTransition?.progress).isEqualTo(0f) progress = .5f @@ -242,7 +242,7 @@ class SceneTransitionLayoutStateTest { val childTransition = transition(SceneB, SceneA) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneB, SceneA)).isTrue() assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) @@ -256,7 +256,7 @@ class SceneTransitionLayoutStateTest { val (parentState, childState) = setupLinkedStates() val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) childState.finishTransition(childTransition, SceneA) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneA)) @@ -268,7 +268,7 @@ class SceneTransitionLayoutStateTest { val (parentState, childState) = setupLinkedStates() val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) childState.finishTransition(childTransition, SceneD) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneD)) @@ -283,16 +283,16 @@ class SceneTransitionLayoutStateTest { transition( SceneA, SceneB, - onFinish = { launch { /* Do nothing. */} }, + onFinish = { launch { /* Do nothing. */ } }, ) val parentTransition = transition( SceneC, SceneA, - onFinish = { launch { /* Do nothing. */} }, + onFinish = { launch { /* Do nothing. */ } }, ) - childState.startTransition(childTransition, null) - parentState.startTransition(parentTransition, null) + childState.startTransition(childTransition) + parentState.startTransition(parentTransition) childState.finishTransition(childTransition, SceneB) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) @@ -341,10 +341,7 @@ class SceneTransitionLayoutStateTest { @Test fun snapToIdleIfClose_snapToStart() = runMonotonicClockTest { val state = MutableSceneTransitionLayoutStateImpl(SceneA, SceneTransitions.Empty) - state.startTransition( - transition(from = SceneA, to = SceneB, progress = { 0.2f }), - transitionKey = null - ) + state.startTransition(transition(from = SceneA, to = SceneB, progress = { 0.2f })) assertThat(state.isTransitioning()).isTrue() // Ignore the request if the progress is not close to 0 or 1, using the threshold. @@ -360,10 +357,7 @@ class SceneTransitionLayoutStateTest { @Test fun snapToIdleIfClose_snapToEnd() = runMonotonicClockTest { val state = MutableSceneTransitionLayoutStateImpl(SceneA, SceneTransitions.Empty) - state.startTransition( - transition(from = SceneA, to = SceneB, progress = { 0.8f }), - transitionKey = null - ) + state.startTransition(transition(from = SceneA, to = SceneB, progress = { 0.8f })) assertThat(state.isTransitioning()).isTrue() // Ignore the request if the progress is not close to 0 or 1, using the threshold. @@ -385,13 +379,13 @@ class SceneTransitionLayoutStateTest { from = SceneA, to = SceneB, progress = { 0.5f }, - onFinish = { launch { /* do nothing */} }, + onFinish = { launch { /* do nothing */ } }, ) - state.startTransition(aToB, transitionKey = null) + state.startTransition(aToB) assertThat(state.currentTransitions).containsExactly(aToB).inOrder() val bToC = transition(from = SceneB, to = SceneC, progress = { 0.8f }) - state.startTransition(bToC, transitionKey = null) + state.startTransition(bToC) assertThat(state.currentTransitions).containsExactly(aToB, bToC).inOrder() // Ignore the request if the progress is not close to 0 or 1, using the threshold. @@ -409,7 +403,7 @@ class SceneTransitionLayoutStateTest { val (parentState, childState) = setupLinkedStates(SceneC, SceneA, null, null, null, SceneD) val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() @@ -425,7 +419,7 @@ class SceneTransitionLayoutStateTest { val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() @@ -440,7 +434,7 @@ class SceneTransitionLayoutStateTest { setupLinkedStates(SceneC, SceneA, SceneB, null, SceneC, SceneD) val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition, null) + childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isFalse() } @@ -460,8 +454,7 @@ class SceneTransitionLayoutStateTest { to = SceneB, progress = progress, orientation = Orientation.Vertical, - ), - transitionKey = null + ) ) assertThat(state.isTransitioning()).isTrue() return state @@ -583,19 +576,19 @@ class SceneTransitionLayoutStateTest { assertThat(state.currentTransitions).isEmpty() // A => B. - state.startTransition(aToB, transitionKey = null) + state.startTransition(aToB) assertThat(finishingTransitions).isEmpty() assertThat(state.finishedTransitions).isEmpty() assertThat(state.currentTransitions).containsExactly(aToB).inOrder() // B => C. This should automatically call finish() on aToB. - state.startTransition(bToC, transitionKey = null) + state.startTransition(bToC) assertThat(finishingTransitions).containsExactly(aToB) assertThat(state.finishedTransitions).isEmpty() assertThat(state.currentTransitions).containsExactly(aToB, bToC).inOrder() // C => A. This should automatically call finish() on bToC. - state.startTransition(cToA, transitionKey = null) + state.startTransition(cToA) assertThat(finishingTransitions).containsExactly(aToB, bToC) assertThat(state.finishedTransitions).isEmpty() assertThat(state.currentTransitions).containsExactly(aToB, bToC, cToA).inOrder() @@ -617,8 +610,8 @@ class SceneTransitionLayoutStateTest { val state = MutableSceneTransitionLayoutStateImpl(SceneA, EmptyTestTransitions) fun startTransition() { - val transition = transition(SceneA, SceneB, onFinish = { launch { /* do nothing */} }) - state.startTransition(transition, transitionKey = null) + val transition = transition(SceneA, SceneB, onFinish = { launch { /* do nothing */ } }) + state.startTransition(transition) } var hasLoggedWtf = false |