Loading packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +6 −35 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.round import androidx.compose.ui.util.fastCoerceIn import com.android.compose.animation.scene.content.Content import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.animation.scene.content.state.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified import com.android.compose.nestedscroll.OnStopScope import com.android.compose.nestedscroll.PriorityNestedScrollConnection Loading Loading @@ -543,19 +542,6 @@ internal class NestedScrollHandlerImpl( val connection: PriorityNestedScrollConnection = nestedScrollConnection() private fun resolveSwipe( isUpOrLeft: Boolean, pointersDown: PointersInfo.PointersDown?, ): Swipe.Resolved { return resolveSwipe( orientation = draggableHandler.orientation, isUpOrLeft = isUpOrLeft, pointersDown = pointersDown, fromSource = pointersDown?.let { draggableHandler.resolveSwipeSource(it.startedPosition) }, ) } private fun nestedScrollConnection(): PriorityNestedScrollConnection { // If we performed a long gesture before entering priority mode, we would have to avoid // moving on to the next scene. Loading @@ -563,23 +549,8 @@ internal class NestedScrollHandlerImpl( var lastPointersDown: PointersInfo.PointersDown? = null fun hasNextScene(amount: Float): Boolean { val transitionState = layoutState.transitionState val scene = transitionState.currentScene val fromScene = layoutImpl.scene(scene) val resolvedSwipe = when { amount < 0f -> resolveSwipe(isUpOrLeft = true, lastPointersDown) amount > 0f -> resolveSwipe(isUpOrLeft = false, lastPointersDown) else -> null } val nextScene = resolvedSwipe?.let { fromScene.findActionResultBestMatch(it) } if (nextScene != null) return true if (transitionState !is TransitionState.Idle) return false val overscrollSpec = layoutImpl.state.transitions.overscrollSpec(scene, orientation) return overscrollSpec != null fun shouldEnableSwipes(): Boolean { return layoutImpl.contentForUserActions().shouldEnableSwipes(orientation) } var isIntercepting = false Loading Loading @@ -650,17 +621,17 @@ internal class NestedScrollHandlerImpl( when (behavior) { NestedScrollBehavior.EdgeNoPreview -> { canChangeScene = isZeroOffset isZeroOffset && hasNextScene(offsetAvailable) isZeroOffset && shouldEnableSwipes() } NestedScrollBehavior.EdgeWithPreview -> { canChangeScene = isZeroOffset hasNextScene(offsetAvailable) shouldEnableSwipes() } NestedScrollBehavior.EdgeAlways -> { canChangeScene = true hasNextScene(offsetAvailable) shouldEnableSwipes() } } Loading Loading @@ -693,7 +664,7 @@ internal class NestedScrollHandlerImpl( } lastPointersDown = pointersDown val canStart = behavior.canStartOnPostFling && hasNextScene(velocityAvailable) val canStart = behavior.canStartOnPostFling && shouldEnableSwipes() if (canStart) { isIntercepting = false } Loading packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ private fun DraggableHandlerImpl.contentForSwipes(): Content { } /** Whether swipe should be enabled in the given [orientation]. */ private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean { internal fun Content.shouldEnableSwipes(orientation: Orientation): Boolean { if (userActions.isEmpty()) { return false } Loading packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt +29 −0 Original line number Diff line number Diff line Loading @@ -1676,4 +1676,33 @@ class DraggableHandlerTest { assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayB) } @Test fun replaceOverlayNestedScroll() = runGestureTest { layoutState.showOverlay(OverlayA, animationScope = testScope) advanceUntilIdle() // Initial state. assertThat(layoutState.transitionState).isIdle() assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayA) // Swipe down to replace overlay A by overlay B. val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview) nestedScroll.scroll(downOffset(0.1f)) val transition = assertThat(layoutState.transitionState).isReplaceOverlayTransition() assertThat(transition).hasCurrentScene(SceneA) assertThat(transition).hasFromOverlay(OverlayA) assertThat(transition).hasToOverlay(OverlayB) assertThat(transition).hasCurrentOverlays(OverlayA) assertThat(transition).hasProgress(0.1f) nestedScroll.preFling(Velocity(0f, velocityThreshold)) advanceUntilIdle() // Commit the gesture. The overlays are instantly swapped in the set of current overlays. assertThat(layoutState.transitionState).isIdle() assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayB) } } Loading
packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +6 −35 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.round import androidx.compose.ui.util.fastCoerceIn import com.android.compose.animation.scene.content.Content import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.animation.scene.content.state.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified import com.android.compose.nestedscroll.OnStopScope import com.android.compose.nestedscroll.PriorityNestedScrollConnection Loading Loading @@ -543,19 +542,6 @@ internal class NestedScrollHandlerImpl( val connection: PriorityNestedScrollConnection = nestedScrollConnection() private fun resolveSwipe( isUpOrLeft: Boolean, pointersDown: PointersInfo.PointersDown?, ): Swipe.Resolved { return resolveSwipe( orientation = draggableHandler.orientation, isUpOrLeft = isUpOrLeft, pointersDown = pointersDown, fromSource = pointersDown?.let { draggableHandler.resolveSwipeSource(it.startedPosition) }, ) } private fun nestedScrollConnection(): PriorityNestedScrollConnection { // If we performed a long gesture before entering priority mode, we would have to avoid // moving on to the next scene. Loading @@ -563,23 +549,8 @@ internal class NestedScrollHandlerImpl( var lastPointersDown: PointersInfo.PointersDown? = null fun hasNextScene(amount: Float): Boolean { val transitionState = layoutState.transitionState val scene = transitionState.currentScene val fromScene = layoutImpl.scene(scene) val resolvedSwipe = when { amount < 0f -> resolveSwipe(isUpOrLeft = true, lastPointersDown) amount > 0f -> resolveSwipe(isUpOrLeft = false, lastPointersDown) else -> null } val nextScene = resolvedSwipe?.let { fromScene.findActionResultBestMatch(it) } if (nextScene != null) return true if (transitionState !is TransitionState.Idle) return false val overscrollSpec = layoutImpl.state.transitions.overscrollSpec(scene, orientation) return overscrollSpec != null fun shouldEnableSwipes(): Boolean { return layoutImpl.contentForUserActions().shouldEnableSwipes(orientation) } var isIntercepting = false Loading Loading @@ -650,17 +621,17 @@ internal class NestedScrollHandlerImpl( when (behavior) { NestedScrollBehavior.EdgeNoPreview -> { canChangeScene = isZeroOffset isZeroOffset && hasNextScene(offsetAvailable) isZeroOffset && shouldEnableSwipes() } NestedScrollBehavior.EdgeWithPreview -> { canChangeScene = isZeroOffset hasNextScene(offsetAvailable) shouldEnableSwipes() } NestedScrollBehavior.EdgeAlways -> { canChangeScene = true hasNextScene(offsetAvailable) shouldEnableSwipes() } } Loading Loading @@ -693,7 +664,7 @@ internal class NestedScrollHandlerImpl( } lastPointersDown = pointersDown val canStart = behavior.canStartOnPostFling && hasNextScene(velocityAvailable) val canStart = behavior.canStartOnPostFling && shouldEnableSwipes() if (canStart) { isIntercepting = false } Loading
packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ private fun DraggableHandlerImpl.contentForSwipes(): Content { } /** Whether swipe should be enabled in the given [orientation]. */ private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean { internal fun Content.shouldEnableSwipes(orientation: Orientation): Boolean { if (userActions.isEmpty()) { return false } Loading
packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt +29 −0 Original line number Diff line number Diff line Loading @@ -1676,4 +1676,33 @@ class DraggableHandlerTest { assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayB) } @Test fun replaceOverlayNestedScroll() = runGestureTest { layoutState.showOverlay(OverlayA, animationScope = testScope) advanceUntilIdle() // Initial state. assertThat(layoutState.transitionState).isIdle() assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayA) // Swipe down to replace overlay A by overlay B. val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview) nestedScroll.scroll(downOffset(0.1f)) val transition = assertThat(layoutState.transitionState).isReplaceOverlayTransition() assertThat(transition).hasCurrentScene(SceneA) assertThat(transition).hasFromOverlay(OverlayA) assertThat(transition).hasToOverlay(OverlayB) assertThat(transition).hasCurrentOverlays(OverlayA) assertThat(transition).hasProgress(0.1f) nestedScroll.preFling(Velocity(0f, velocityThreshold)) advanceUntilIdle() // Commit the gesture. The overlays are instantly swapped in the set of current overlays. assertThat(layoutState.transitionState).isIdle() assertThat(layoutState.transitionState).hasCurrentScene(SceneA) assertThat(layoutState.transitionState).hasCurrentOverlays(OverlayB) } }