summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author omarmt <omarmt@google.com> 2024-09-27 15:13:59 +0000
committer omarmt <omarmt@google.com> 2024-10-01 12:15:54 +0000
commitf0b04418efebff13dcb2757ee39714f2ba95fae7 (patch)
tree05906070b783a3dfbbee449bd3b303b0427963b8
parent1e34a1dfac75048f0dfc93196c0e18f4f2a80132 (diff)
Add support for fromSource in nested scroll
STL's nested scroll connection now uses the information available in the DraggableHandler to compute the current action (Swipe.Resolved). Test: atest DraggableHandlerTest Bug: 366387626 Flag: com.android.systemui.scene_container Change-Id: Ib6b53679de0a3a1aa8bf4fe096f3bb04f3292c8f
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt49
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt3
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt56
3 files changed, 74 insertions, 34 deletions
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 367faed7b7f7..84fea557ffc4 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
@@ -188,7 +188,7 @@ internal class DraggableHandlerImpl(
return createSwipeAnimation(layoutImpl, result, isUpOrLeft, orientation)
}
- private fun resolveSwipeSource(startedPosition: Offset?): SwipeSource.Resolved? {
+ internal fun resolveSwipeSource(startedPosition: Offset?): SwipeSource.Resolved? {
if (startedPosition == null) return null
return layoutImpl.swipeSourceDetector.source(
layoutSize = layoutImpl.lastSize,
@@ -198,7 +198,7 @@ internal class DraggableHandlerImpl(
)
}
- private fun resolveSwipe(
+ internal fun resolveSwipe(
pointersDown: Int,
fromSource: SwipeSource.Resolved?,
isUpOrLeft: Boolean,
@@ -558,6 +558,14 @@ internal class NestedScrollHandlerImpl(
val connection: PriorityNestedScrollConnection = nestedScrollConnection()
+ private fun PointersInfo.resolveSwipe(isUpOrLeft: Boolean): Swipe.Resolved {
+ return draggableHandler.resolveSwipe(
+ pointersDown = pointersDown,
+ fromSource = draggableHandler.resolveSwipeSource(startedPosition),
+ isUpOrLeft = isUpOrLeft,
+ )
+ }
+
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.
@@ -574,36 +582,19 @@ internal class NestedScrollHandlerImpl(
val transitionState = layoutState.transitionState
val scene = transitionState.currentScene
val fromScene = layoutImpl.scene(scene)
- val nextScene =
+ val resolvedSwipe =
when {
- amount < 0f -> {
- val actionUpOrLeft =
- Swipe.Resolved(
- direction =
- when (orientation) {
- Orientation.Horizontal -> SwipeDirection.Resolved.Left
- Orientation.Vertical -> SwipeDirection.Resolved.Up
- },
- pointerCount = pointersInfo().pointersDown,
- fromSource = null,
- )
- fromScene.userActions[actionUpOrLeft]
- }
- amount > 0f -> {
- val actionDownOrRight =
- Swipe.Resolved(
- direction =
- when (orientation) {
- Orientation.Horizontal -> SwipeDirection.Resolved.Right
- Orientation.Vertical -> SwipeDirection.Resolved.Down
- },
- pointerCount = pointersInfo().pointersDown,
- fromSource = null,
- )
- fromScene.userActions[actionDownOrRight]
- }
+ amount < 0f -> pointersInfo().resolveSwipe(isUpOrLeft = true)
+ amount > 0f -> pointersInfo().resolveSwipe(isUpOrLeft = false)
else -> null
}
+ val nextScene =
+ resolvedSwipe?.let {
+ fromScene.userActions[it]
+ ?: if (it.fromSource != null) {
+ fromScene.userActions[it.copy(fromSource = null)]
+ } else null
+ }
if (nextScene != null) return true
if (transitionState !is TransitionState.Idle) return false
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 0bb1d928c2b4..ab11be8b671f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -213,8 +213,9 @@ internal class MultiPointerDraggableNode(
internal fun pointersInfo(): PointersInfo {
return PointersInfo(
+ // This may be null, i.e. when the user uses TalkBack
startedPosition = startedPosition,
- // Note: We could have 0 pointers during fling or for other reasons.
+ // We could have 0 pointers during fling or for other reasons.
pointersDown = pointersDown.coerceAtLeast(1),
)
}
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 b64b8be90ad2..6972dbe49019 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
@@ -129,6 +129,10 @@ class DraggableHandlerTest {
val draggableHandler = layoutImpl.draggableHandler(Orientation.Vertical)
val horizontalDraggableHandler = layoutImpl.draggableHandler(Orientation.Horizontal)
+ var pointerInfoOwner: () -> PointersInfo = {
+ PointersInfo(startedPosition = Offset.Zero, pointersDown = 1)
+ }
+
fun nestedScrollConnection(
nestedScrollBehavior: NestedScrollBehavior,
isExternalOverscrollGesture: Boolean = false,
@@ -139,9 +143,7 @@ class DraggableHandlerTest {
topOrLeftBehavior = nestedScrollBehavior,
bottomOrRightBehavior = nestedScrollBehavior,
isExternalOverscrollGesture = { isExternalOverscrollGesture },
- pointersInfoOwner = {
- PointersInfo(startedPosition = Offset.Zero, pointersDown = 1)
- },
+ pointersInfoOwner = { pointerInfoOwner() },
)
.connection
@@ -155,11 +157,18 @@ class DraggableHandlerTest {
fun downOffset(fractionOfScreen: Float) =
if (fractionOfScreen < 0f) {
- error("upOffset() is required, not implemented yet")
+ error("use upOffset()")
} else {
Offset(x = 0f, y = down(fractionOfScreen))
}
+ fun upOffset(fractionOfScreen: Float) =
+ if (fractionOfScreen < 0f) {
+ error("use downOffset()")
+ } else {
+ Offset(x = 0f, y = up(fractionOfScreen))
+ }
+
val transitionState: TransitionState
get() = layoutState.transitionState
@@ -1071,6 +1080,45 @@ class DraggableHandlerTest {
}
@Test
+ fun nestedScrollUseFromSourceInfo() = runGestureTest {
+ // Start at scene C.
+ navigateToSceneC()
+ val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
+
+ // Drag from the **top** of the screen
+ pointerInfoOwner = { PointersInfo(startedPosition = Offset(0f, 0f), pointersDown = 1) }
+ assertIdle(currentScene = SceneC)
+
+ nestedScroll.scroll(available = upOffset(fractionOfScreen = 0.1f))
+ assertTransition(
+ currentScene = SceneC,
+ fromScene = SceneC,
+ // userAction: Swipe.Up to SceneB
+ toScene = SceneB,
+ progress = 0.1f,
+ )
+
+ // Reset to SceneC
+ nestedScroll.preFling(Velocity.Zero)
+ advanceUntilIdle()
+
+ // Drag from the **bottom** of the screen
+ pointerInfoOwner = {
+ PointersInfo(startedPosition = Offset(0f, SCREEN_SIZE), pointersDown = 1)
+ }
+ assertIdle(currentScene = SceneC)
+
+ nestedScroll.scroll(available = upOffset(fractionOfScreen = 0.1f))
+ assertTransition(
+ currentScene = SceneC,
+ fromScene = SceneC,
+ // userAction: Swipe(SwipeDirection.Up, fromSource = Edge.Bottom) to SceneA
+ toScene = SceneA,
+ progress = 0.1f,
+ )
+ }
+
+ @Test
fun transitionIsImmediatelyUpdatedWhenReleasingFinger() = runGestureTest {
// Swipe up from the middle to transition to scene B.
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)