diff options
2 files changed, 47 insertions, 3 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt index 99a9777a99b8..56523e07186c 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt @@ -218,8 +218,8 @@ internal class SwipeAnimation<T : ContentKey>( val animatable = offsetAnimation val offset = when { + isInPreviewStage -> 0f animatable != null -> animatable.value - contentTransition.previewTransformationSpec != null -> 0f else -> dragOffset } @@ -247,7 +247,15 @@ internal class SwipeAnimation<T : ContentKey>( } val previewProgress: Float - get() = computeProgress(dragOffset) + get() { + val offset = + if (isInPreviewStage) { + offsetAnimation?.value ?: dragOffset + } else { + dragOffset + } + return computeProgress(offset) + } val previewProgressVelocity: Float get() = 0f @@ -347,7 +355,11 @@ internal class SwipeAnimation<T : ContentKey>( } val startProgress = - if (contentTransition.previewTransformationSpec != null) 0f else dragOffset + if (contentTransition.previewTransformationSpec != null && targetContent == toContent) { + 0f + } else { + dragOffset + } val animatable = Animatable(startProgress, OffsetVisibilityThreshold).also { offsetAnimation = it } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt index 26743fc83c7f..79f82c948541 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt @@ -200,6 +200,8 @@ class DraggableHandlerTest { fromScene: SceneKey? = null, toScene: SceneKey? = null, progress: Float? = null, + previewProgress: Float? = null, + isInPreviewStage: Boolean? = null, isUserInputOngoing: Boolean? = null ): Transition { val transition = assertThat(transitionState).isSceneTransition() @@ -207,6 +209,10 @@ class DraggableHandlerTest { fromScene?.let { assertThat(transition).hasFromScene(it) } toScene?.let { assertThat(transition).hasToScene(it) } progress?.let { assertThat(transition).hasProgress(it) } + previewProgress?.let { assertThat(transition).hasPreviewProgress(it) } + isInPreviewStage?.let { + assertThat(transition).run { if (it) isInPreviewStage() else isNotInPreviewStage() } + } isUserInputOngoing?.let { assertThat(transition).hasIsUserInputOngoing(it) } return transition } @@ -353,6 +359,32 @@ class DraggableHandlerTest { } @Test + fun onDragStoppedAfterDrag_velocityLowerThanThreshold_remainSameScene_previewAnimated() = + runGestureTest { + layoutState.transitions = transitions { + // set a preview for the transition + from(SceneA, to = SceneC, preview = {}) {} + } + val dragController = onDragStarted(overSlop = down(fractionOfScreen = 0.1f)) + assertTransition(currentScene = SceneA) + + dragController.onDragStopped(velocity = velocityThreshold - 0.01f) + runCurrent() + + // verify that transition remains in preview stage and animates back to fromScene + assertTransition( + currentScene = SceneA, + isInPreviewStage = true, + previewProgress = 0.1f, + progress = 0f + ) + + // wait for the stop animation + advanceUntilIdle() + assertIdle(currentScene = SceneA) + } + + @Test fun onDragStoppedAfterDrag_velocityAtLeastThreshold_goToNextScene() = runGestureTest { val dragController = onDragStarted(overSlop = down(fractionOfScreen = 0.1f)) assertTransition(currentScene = SceneA) |