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

Commit b87dbb2a authored by Justin Weir's avatar Justin Weir Committed by Android (Google) Code Review
Browse files

Merge changes I03605687,I6a7dd88d into main

* changes:
  Add scene based isUserInteracting flow implementations
  Add isUserInputDriven to transitions
parents 1c915fde e37c87a7
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -107,6 +107,9 @@ private fun CoroutineScope.animate(
    reversed: Boolean = false,
) {
    val fromScene = layoutImpl.state.transitionState.currentScene
    val isUserInput =
        (layoutImpl.state.transitionState as? TransitionState.Transition)?.isUserInputDriven
            ?: false

    val animationSpec = layoutImpl.transitions.transitionSpec(fromScene, target).spec
    val visibilityThreshold =
@@ -116,9 +119,9 @@ private fun CoroutineScope.animate(
    val targetProgress = if (reversed) 0f else 1f
    val transition =
        if (reversed) {
            OneOffTransition(target, fromScene, currentScene = target, animatable)
            OneOffTransition(target, fromScene, currentScene = target, isUserInput, animatable)
        } else {
            OneOffTransition(fromScene, target, currentScene = target, animatable)
            OneOffTransition(fromScene, target, currentScene = target, isUserInput, animatable)
        }

    // Change the current layout state to use this new transition.
@@ -139,6 +142,7 @@ private class OneOffTransition(
    override val fromScene: SceneKey,
    override val toScene: SceneKey,
    override val currentScene: SceneKey,
    override val isUserInputDriven: Boolean,
    private val animatable: Animatable<Float, AnimationVector1D>,
) : TransitionState.Transition {
    override val progress: Float
+12 −0
Original line number Diff line number Diff line
@@ -42,6 +42,17 @@ sealed class ObservableTransitionState {
        val fromScene: SceneKey,
        val toScene: SceneKey,
        val progress: Flow<Float>,

        /**
         * Whether the transition was originally triggered by user input rather than being
         * programmatic. If this value is initially true, it will remain true until the transition
         * fully completes, even if the user input that triggered the transition has ended. Any
         * sub-transitions launched by this one will inherit this value. For example, if the user
         * drags a pointer but does not exceed the threshold required to transition to another
         * scene, this value will remain true after the pointer is no longer touching the screen and
         * will be true in any transition created to animate back to the original position.
         */
        val isUserInputDriven: Boolean,
    ) : ObservableTransitionState()
}

@@ -62,6 +73,7 @@ fun SceneTransitionLayoutState.observableTransitionState(): Flow<ObservableTrans
                            fromScene = state.fromScene,
                            toScene = state.toScene,
                            progress = snapshotFlow { state.progress },
                            isUserInputDriven = state.isUserInputDriven,
                        )
                    }
                }
+3 −0
Original line number Diff line number Diff line
@@ -68,5 +68,8 @@ sealed interface TransitionState {
         * when flinging quickly during a swipe gesture.
         */
        val progress: Float

        /** Whether the transition was triggered by user input rather than being programmatic. */
        val isUserInputDriven: Boolean
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -137,6 +137,8 @@ private class SwipeTransition(initialScene: Scene) : TransitionState.Transition
            return offset / distance
        }

    override val isUserInputDriven = true

    /** The current offset caused by the drag gesture. */
    var dragOffset by mutableFloatStateOf(0f)

+4 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ class SwipeToSceneTest {
        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
        assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
        assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
        assertThat(transition.isUserInputDriven).isTrue()

        // Release the finger. We should now be animating back to A (currentScene = SceneA) given
        // that 55dp < positional threshold.
@@ -133,6 +134,7 @@ class SwipeToSceneTest {
        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
        assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
        assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
        assertThat(transition.isUserInputDriven).isTrue()

        // Wait for the animation to finish. We should now be in scene A.
        rule.waitForIdle()
@@ -154,6 +156,7 @@ class SwipeToSceneTest {
        assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
        assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
        assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
        assertThat(transition.isUserInputDriven).isTrue()

        // Release the finger. We should now be animating to C (currentScene = SceneC) given
        // that 56dp >= positional threshold.
@@ -165,6 +168,7 @@ class SwipeToSceneTest {
        assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
        assertThat(transition.currentScene).isEqualTo(TestScenes.SceneC)
        assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
        assertThat(transition.isUserInputDriven).isTrue()

        // Wait for the animation to finish. We should now be in scene C.
        rule.waitForIdle()
Loading