diff options
10 files changed, 74 insertions, 56 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt index c073b79ba5a3..bbba826fe863 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt @@ -85,13 +85,14 @@ fun CommunalContainer( SceneTransitionLayout( state = sceneTransitionLayoutState, modifier = modifier.fillMaxSize(), - edgeDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize), + swipeSourceDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize), ) { scene( TransitionSceneKey.Blank, userActions = mapOf( - Swipe(SwipeDirection.Left, fromEdge = Edge.Right) to TransitionSceneKey.Communal + Swipe(SwipeDirection.Left, fromSource = Edge.Right) to + TransitionSceneKey.Communal ) ) { // This scene shows nothing only allowing for transitions to the communal scene. @@ -102,7 +103,7 @@ fun CommunalContainer( TransitionSceneKey.Communal, userActions = mapOf( - Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to TransitionSceneKey.Blank + Swipe(SwipeDirection.Right, fromSource = Edge.Left) to TransitionSceneKey.Blank ), ) { CommunalScene(viewModel, modifier = modifier) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt index c35202cd830a..9f9e1f5bb56a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt @@ -183,7 +183,7 @@ private fun UserAction.toTransitionUserAction(): SceneTransitionUserAction { is UserAction.Swipe -> Swipe( pointerCount = pointerCount, - fromEdge = + fromSource = when (this.fromEdge) { null -> null Edge.LEFT -> SceneTransitionEdge.Left diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt index 82d4239d7eb5..b0dc3a144533 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt @@ -23,24 +23,19 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -interface EdgeDetector { - /** - * Return the [Edge] associated to [position] inside a layout of size [layoutSize], given - * [density] and [orientation]. - */ - fun edge( - layoutSize: IntSize, - position: IntOffset, - density: Density, - orientation: Orientation, - ): Edge? +/** The edge of a [SceneTransitionLayout]. */ +enum class Edge : SwipeSource { + Left, + Right, + Top, + Bottom, } val DefaultEdgeDetector = FixedSizeEdgeDetector(40.dp) -/** An [EdgeDetector] that detects edges assuming a fixed edge size of [size]. */ -class FixedSizeEdgeDetector(val size: Dp) : EdgeDetector { - override fun edge( +/** An [SwipeSourceDetector] that detects edges assuming a fixed edge size of [size]. */ +class FixedSizeEdgeDetector(val size: Dp) : SwipeSourceDetector { + override fun source( layoutSize: IntSize, position: IntOffset, density: Density, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt index 0a2370a93dd6..333eef73739f 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt @@ -80,8 +80,8 @@ internal class SceneGestureHandler( /** The [Swipe]s associated to the current gesture. */ private var upOrLeftSwipe: Swipe? = null private var downOrRightSwipe: Swipe? = null - private var upOrLeftNoEdgeSwipe: Swipe? = null - private var downOrRightNoEdgeSwipe: Swipe? = null + private var upOrLeftNoSourceSwipe: Swipe? = null + private var downOrRightNoSourceSwipe: Swipe? = null /** The [UserActionResult] associated to up and down swipes. */ private var upOrLeftResult: UserActionResult? = null @@ -117,9 +117,9 @@ internal class SceneGestureHandler( } private fun setCurrentActions(fromScene: Scene, startedPosition: Offset?, pointersDown: Int) { - val fromEdge = + val fromSource = startedPosition?.let { position -> - layoutImpl.edgeDetector.edge( + layoutImpl.swipeSourceDetector.source( fromScene.targetSize, position.round(), layoutImpl.density, @@ -135,7 +135,7 @@ internal class SceneGestureHandler( Orientation.Vertical -> SwipeDirection.Up }, pointerCount = pointersDown, - fromEdge = fromEdge, + fromSource = fromSource, ) val downOrRight = @@ -146,19 +146,19 @@ internal class SceneGestureHandler( Orientation.Vertical -> SwipeDirection.Down }, pointerCount = pointersDown, - fromEdge = fromEdge, + fromSource = fromSource, ) - if (fromEdge == null) { + if (fromSource == null) { upOrLeftSwipe = null downOrRightSwipe = null - upOrLeftNoEdgeSwipe = upOrLeft - downOrRightNoEdgeSwipe = downOrRight + upOrLeftNoSourceSwipe = upOrLeft + downOrRightNoSourceSwipe = downOrRight } else { upOrLeftSwipe = upOrLeft downOrRightSwipe = downOrRight - upOrLeftNoEdgeSwipe = upOrLeft.copy(fromEdge = null) - downOrRightNoEdgeSwipe = downOrRight.copy(fromEdge = null) + upOrLeftNoSourceSwipe = upOrLeft.copy(fromSource = null) + downOrRightNoSourceSwipe = downOrRight.copy(fromSource = null) } } @@ -204,9 +204,9 @@ internal class SceneGestureHandler( return userActions[swipe ?: return null] } - upOrLeftResult = sceneToSwipePair(upOrLeftSwipe) ?: sceneToSwipePair(upOrLeftNoEdgeSwipe) + upOrLeftResult = sceneToSwipePair(upOrLeftSwipe) ?: sceneToSwipePair(upOrLeftNoSourceSwipe) downOrRightResult = - sceneToSwipePair(downOrRightSwipe) ?: sceneToSwipePair(downOrRightNoEdgeSwipe) + sceneToSwipePair(downOrRightSwipe) ?: sceneToSwipePair(downOrRightNoSourceSwipe) } /** diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt index aa232df97aed..7e0aa9c3e2b1 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize /** @@ -41,7 +42,8 @@ import androidx.compose.ui.unit.IntSize * UI code. * * @param state the state of this layout. - * @param edgeDetector the edge detector used to detect which edge a swipe is started from, if any. + * @param swipeSourceDetector the edge detector used to detect which edge a swipe is started from, + * if any. * @param transitionInterceptionThreshold used during a scene transition. For the scene to be * intercepted, the progress value must be above the threshold, and below (1 - threshold). * @param scenes the configuration of the different scenes of this layout. @@ -51,14 +53,14 @@ import androidx.compose.ui.unit.IntSize fun SceneTransitionLayout( state: SceneTransitionLayoutState, modifier: Modifier = Modifier, - edgeDetector: EdgeDetector = DefaultEdgeDetector, + swipeSourceDetector: SwipeSourceDetector = DefaultEdgeDetector, @FloatRange(from = 0.0, to = 0.5) transitionInterceptionThreshold: Float = 0f, scenes: SceneTransitionLayoutScope.() -> Unit, ) { SceneTransitionLayoutForTesting( state, modifier, - edgeDetector, + swipeSourceDetector, transitionInterceptionThreshold, onLayoutImpl = null, scenes, @@ -79,7 +81,8 @@ fun SceneTransitionLayout( * This is called when the user commits a transition to a new scene because of a [UserAction], for * instance by triggering back navigation or by swiping to a new scene. * @param transitions the definition of the transitions used to animate a change of scene. - * @param edgeDetector the edge detector used to detect which edge a swipe is started from, if any. + * @param swipeSourceDetector the source detector used to detect which source a swipe is started + * from, if any. * @param transitionInterceptionThreshold used during a scene transition. For the scene to be * intercepted, the progress value must be above the threshold, and below (1 - threshold). * @param scenes the configuration of the different scenes of this layout. @@ -90,7 +93,7 @@ fun SceneTransitionLayout( onChangeScene: (SceneKey) -> Unit, transitions: SceneTransitions, modifier: Modifier = Modifier, - edgeDetector: EdgeDetector = DefaultEdgeDetector, + swipeSourceDetector: SwipeSourceDetector = DefaultEdgeDetector, @FloatRange(from = 0.0, to = 0.5) transitionInterceptionThreshold: Float = 0f, scenes: SceneTransitionLayoutScope.() -> Unit, ) { @@ -98,7 +101,7 @@ fun SceneTransitionLayout( SceneTransitionLayout( state, modifier, - edgeDetector, + swipeSourceDetector, transitionInterceptionThreshold, scenes, ) @@ -338,7 +341,7 @@ data object Back : UserAction data class Swipe( val direction: SwipeDirection, val pointerCount: Int = 1, - val fromEdge: Edge? = null, + val fromSource: SwipeSource? = null, ) : UserAction { companion object { val Left = Swipe(SwipeDirection.Left) @@ -356,6 +359,33 @@ enum class SwipeDirection(val orientation: Orientation) { } /** + * The source of a Swipe. + * + * Important: This can be anything that can be returned by any [SwipeSourceDetector], but this must + * implement [equals] and [hashCode]. Note that those can be trivially implemented using data + * classes. + */ +interface SwipeSource { + // Require equals() and hashCode() to be implemented. + override fun equals(other: Any?): Boolean + + override fun hashCode(): Int +} + +interface SwipeSourceDetector { + /** + * Return the [SwipeSource] associated to [position] inside a layout of size [layoutSize], given + * [density] and [orientation]. + */ + fun source( + layoutSize: IntSize, + position: IntOffset, + density: Density, + orientation: Orientation, + ): SwipeSource? +} + +/** * The result of performing a [UserAction]. * * Note: [UserActionResult] is implemented by [SceneKey], and you can also use [withDistance] to @@ -427,7 +457,7 @@ private class FixedDistance(private val distance: Dp) : UserActionDistance { internal fun SceneTransitionLayoutForTesting( state: SceneTransitionLayoutState, modifier: Modifier = Modifier, - edgeDetector: EdgeDetector = DefaultEdgeDetector, + swipeSourceDetector: SwipeSourceDetector = DefaultEdgeDetector, transitionInterceptionThreshold: Float = 0f, onLayoutImpl: ((SceneTransitionLayoutImpl) -> Unit)? = null, scenes: SceneTransitionLayoutScope.() -> Unit, @@ -438,7 +468,7 @@ internal fun SceneTransitionLayoutForTesting( SceneTransitionLayoutImpl( state = state as BaseSceneTransitionLayoutState, density = density, - edgeDetector = edgeDetector, + swipeSourceDetector = swipeSourceDetector, transitionInterceptionThreshold = transitionInterceptionThreshold, builder = scenes, coroutineScope = coroutineScope, @@ -459,7 +489,7 @@ internal fun SceneTransitionLayoutForTesting( } layoutImpl.density = density - layoutImpl.edgeDetector = edgeDetector + layoutImpl.swipeSourceDetector = swipeSourceDetector } layoutImpl.Content(modifier) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt index 982b0e0f8f99..8c5a4720e7fb 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt @@ -47,7 +47,7 @@ internal typealias MovableElementContent = internal class SceneTransitionLayoutImpl( internal val state: BaseSceneTransitionLayoutState, internal var density: Density, - internal var edgeDetector: EdgeDetector, + internal var swipeSourceDetector: SwipeSourceDetector, internal var transitionInterceptionThreshold: Float, builder: SceneTransitionLayoutScope.() -> Unit, private val coroutineScope: CoroutineScope, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt index dc8505c43889..a764a52723af 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt @@ -320,11 +320,3 @@ interface PropertyTransformationBuilder { anchorHeight: Boolean = true, ) } - -/** The edge of a [SceneTransitionLayout]. */ -enum class Edge { - Left, - Right, - Top, - Bottom, -} diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt index a68282ae78f4..cceaf57ca82b 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt @@ -35,7 +35,7 @@ class FixedSizeEdgeDetectorTest { @Test fun horizontalEdges() { fun horizontalEdge(position: Int): Edge? = - detector.edge( + detector.source( layoutSize, position = IntOffset(position, 0), density, @@ -53,7 +53,7 @@ class FixedSizeEdgeDetectorTest { @Test fun verticalEdges() { fun verticalEdge(position: Int): Edge? = - detector.edge( + detector.source( layoutSize, position = IntOffset(0, position), density, diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt index 066a3e45fb3c..4b3b369ea862 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt @@ -77,7 +77,7 @@ class SceneGestureHandlerTest { userActions = mapOf( Swipe.Up to SceneB, - Swipe(SwipeDirection.Up, fromEdge = Edge.Bottom) to SceneA + Swipe(SwipeDirection.Up, fromSource = Edge.Bottom) to SceneA ), ) { Text("SceneC") @@ -90,7 +90,7 @@ class SceneGestureHandlerTest { SceneTransitionLayoutImpl( state = layoutState, density = Density(1f), - edgeDetector = DefaultEdgeDetector, + swipeSourceDetector = DefaultEdgeDetector, transitionInterceptionThreshold = transitionInterceptionThreshold, builder = scenesBuilder, coroutineScope = coroutineScope, diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt index 4571d8ea6bdf..940335853221 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt @@ -90,8 +90,8 @@ class SwipeToSceneTest { mapOf( Swipe.Down to TestScenes.SceneA, Swipe(SwipeDirection.Down, pointerCount = 2) to TestScenes.SceneB, - Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to TestScenes.SceneB, - Swipe(SwipeDirection.Down, fromEdge = Edge.Top) to TestScenes.SceneB, + Swipe(SwipeDirection.Right, fromSource = Edge.Left) to TestScenes.SceneB, + Swipe(SwipeDirection.Down, fromSource = Edge.Top) to TestScenes.SceneB, ), ) { Box(Modifier.fillMaxSize()) |