summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt29
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt43
2 files changed, 54 insertions, 18 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index ca643231e874..20742ee77fff 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -329,10 +329,9 @@ private fun elementTransition(
if (transition == null && previousTransition != null) {
// The transition was just finished.
- element.sceneStates.values.forEach { sceneState ->
- sceneState.offsetInterruptionDelta = Offset.Zero
- sceneState.scaleInterruptionDelta = Scale.Zero
- sceneState.alphaInterruptionDelta = 0f
+ element.sceneStates.values.forEach {
+ it.clearValuesBeforeInterruption()
+ it.clearInterruptionDeltas()
}
}
@@ -375,12 +374,22 @@ private fun prepareInterruption(element: Element) {
sceneState.scaleBeforeInterruption = lastScale
sceneState.alphaBeforeInterruption = lastAlpha
- sceneState.offsetInterruptionDelta = Offset.Zero
- sceneState.scaleInterruptionDelta = Scale.Zero
- sceneState.alphaInterruptionDelta = 0f
+ sceneState.clearInterruptionDeltas()
}
}
+private fun Element.SceneState.clearInterruptionDeltas() {
+ offsetInterruptionDelta = Offset.Zero
+ scaleInterruptionDelta = Scale.Zero
+ alphaInterruptionDelta = 0f
+}
+
+private fun Element.SceneState.clearValuesBeforeInterruption() {
+ offsetBeforeInterruption = Offset.Unspecified
+ scaleBeforeInterruption = Scale.Unspecified
+ alphaBeforeInterruption = Element.AlphaUnspecified
+}
+
/**
* Compute what [value] should be if we take the
* [interruption progress][TransitionState.Transition.interruptionProgress] of [transition] into
@@ -744,7 +753,11 @@ private fun ApproachMeasureScope.place(
// No need to place the element in this scene if we don't want to draw it anyways.
if (!shouldPlaceElement(layoutImpl, scene, element, transition)) {
sceneState.lastOffset = Offset.Unspecified
- sceneState.offsetBeforeInterruption = Offset.Unspecified
+ sceneState.lastScale = Scale.Unspecified
+ sceneState.lastAlpha = Element.AlphaUnspecified
+
+ sceneState.clearValuesBeforeInterruption()
+ sceneState.clearInterruptionDeltas()
return
}
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 92e1b2cd030c..bbf3d8a5571e 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
@@ -1049,24 +1049,30 @@ class ElementTest {
Box(modifier.element(TestElements.Foo).size(fooSize))
}
+ lateinit var layoutImpl: SceneTransitionLayoutImpl
rule.setContent {
- SceneTransitionLayout(state, Modifier.size(layoutSize)) {
+ SceneTransitionLayoutForTesting(
+ state,
+ Modifier.size(layoutSize),
+ onLayoutImpl = { layoutImpl = it },
+ ) {
// In scene A, Foo is aligned at the TopStart.
scene(SceneA) {
Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopStart)) }
}
+ // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
+ // from B. We put it before (below) scene B so that we can check that interruptions
+ // values and deltas are properly cleared once all transitions are done.
+ scene(SceneC) {
+ Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
+ }
+
// In scene B, Foo is aligned at the TopEnd, so it moves horizontally when coming
// from A.
scene(SceneB) {
Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopEnd)) }
}
-
- // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
- // from B.
- scene(SceneC) {
- Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
- }
}
}
@@ -1115,7 +1121,7 @@ class ElementTest {
// Interruption progress is at 100% and bToC is at 0%, so Foo should be at the same offset
// as right before the interruption.
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(offsetInAToB.x, offsetInAToB.y)
// Move the transition forward at 30% and set the interruption progress to 50%.
@@ -1130,7 +1136,7 @@ class ElementTest {
)
rule.waitForIdle()
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(
offsetInBToCWithInterruption.x,
offsetInBToCWithInterruption.y,
@@ -1140,7 +1146,24 @@ class ElementTest {
bToCProgress = 1f
interruptionProgress = 0f
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(offsetInC.x, offsetInC.y)
+
+ // Manually finish the transition.
+ state.finishTransition(aToB, SceneB)
+ state.finishTransition(bToC, SceneC)
+ rule.waitForIdle()
+ assertThat(state.currentTransition).isNull()
+
+ // The interruption values should be unspecified and deltas should be set to zero.
+ val foo = layoutImpl.elements.getValue(TestElements.Foo)
+ assertThat(foo.sceneStates.keys).containsExactly(SceneC)
+ val stateInC = foo.sceneStates.getValue(SceneC)
+ assertThat(stateInC.offsetBeforeInterruption).isEqualTo(Offset.Unspecified)
+ assertThat(stateInC.scaleBeforeInterruption).isEqualTo(Scale.Unspecified)
+ assertThat(stateInC.alphaBeforeInterruption).isEqualTo(Element.AlphaUnspecified)
+ assertThat(stateInC.offsetInterruptionDelta).isEqualTo(Offset.Zero)
+ assertThat(stateInC.scaleInterruptionDelta).isEqualTo(Scale.Zero)
+ assertThat(stateInC.alphaInterruptionDelta).isEqualTo(0f)
}
}