Added orientation utilities to convert: Offset/Velocity to/from Float
Note: this is a refactor that introduces no new logic
Test: atest SceneGestureHandlerTest
Bug: 291053278
Flag: NA
Change-Id: I1fb9a8fe64e9a7261e33b6ce61869770713c16c3
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 838cb3b..664b509 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
@@ -28,7 +28,6 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
@@ -541,24 +540,6 @@
) : NestedScrollHandler {
override val connection: PriorityNestedScrollConnection = nestedScrollConnection()
- private fun Offset.toAmount() =
- when (gestureHandler.orientation) {
- Orientation.Horizontal -> x
- Orientation.Vertical -> y
- }
-
- private fun Velocity.toAmount() =
- when (gestureHandler.orientation) {
- Orientation.Horizontal -> x
- Orientation.Vertical -> y
- }
-
- private fun Float.toOffset() =
- when (gestureHandler.orientation) {
- Orientation.Horizontal -> Offset(x = this, y = 0f)
- Orientation.Vertical -> Offset(x = 0f, y = this)
- }
-
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.
@@ -596,13 +577,12 @@
}
return PriorityNestedScrollConnection(
+ orientation = gestureHandler.orientation,
canStartPreScroll = { offsetAvailable, offsetBeforeStart ->
- canChangeScene = offsetBeforeStart == Offset.Zero
+ canChangeScene = offsetBeforeStart == 0f
val canInterceptSwipeTransition =
- canChangeScene &&
- gestureHandler.isDrivingTransition &&
- offsetAvailable.toAmount() != 0f
+ canChangeScene && gestureHandler.isDrivingTransition && offsetAvailable != 0f
if (!canInterceptSwipeTransition) return@PriorityNestedScrollConnection false
val progress = gestureHandler.swipeTransition.progress
@@ -623,15 +603,14 @@
!shouldSnapToIdle
},
canStartPostScroll = { offsetAvailable, offsetBeforeStart ->
- val amount = offsetAvailable.toAmount()
val behavior: NestedScrollBehavior =
when {
- amount > 0 -> startBehavior
- amount < 0 -> endBehavior
+ offsetAvailable > 0f -> startBehavior
+ offsetAvailable < 0f -> endBehavior
else -> return@PriorityNestedScrollConnection false
}
- val isZeroOffset = offsetBeforeStart == Offset.Zero
+ val isZeroOffset = offsetBeforeStart == 0f
when (behavior) {
NestedScrollBehavior.DuringTransitionBetweenScenes -> {
@@ -640,30 +619,29 @@
}
NestedScrollBehavior.EdgeNoOverscroll -> {
canChangeScene = isZeroOffset
- isZeroOffset && hasNextScene(amount)
+ isZeroOffset && hasNextScene(offsetAvailable)
}
NestedScrollBehavior.EdgeWithOverscroll -> {
canChangeScene = isZeroOffset
- hasNextScene(amount)
+ hasNextScene(offsetAvailable)
}
NestedScrollBehavior.Always -> {
canChangeScene = true
- hasNextScene(amount)
+ hasNextScene(offsetAvailable)
}
}
},
canStartPostFling = { velocityAvailable ->
- val amount = velocityAvailable.toAmount()
val behavior: NestedScrollBehavior =
when {
- amount > 0 -> startBehavior
- amount < 0 -> endBehavior
+ velocityAvailable > 0f -> startBehavior
+ velocityAvailable < 0f -> endBehavior
else -> return@PriorityNestedScrollConnection false
}
// We could start an overscroll animation
canChangeScene = false
- behavior.canStartOnPostFling && hasNextScene(amount)
+ behavior.canStartOnPostFling && hasNextScene(velocityAvailable)
},
canContinueScroll = { true },
onStart = {
@@ -676,24 +654,22 @@
},
onScroll = { offsetAvailable ->
if (gestureHandler.gestureWithPriority != this) {
- return@PriorityNestedScrollConnection Offset.Zero
+ return@PriorityNestedScrollConnection 0f
}
- val amount = offsetAvailable.toAmount()
-
// TODO(b/297842071) We should handle the overscroll or slow drag if the gesture is
// initiated in a nested child.
- gestureHandler.onDrag(amount)
+ gestureHandler.onDrag(offsetAvailable)
- amount.toOffset()
+ offsetAvailable
},
onStop = { velocityAvailable ->
if (gestureHandler.gestureWithPriority != this) {
- return@PriorityNestedScrollConnection Velocity.Zero
+ return@PriorityNestedScrollConnection 0f
}
gestureHandler.onDragStopped(
- velocity = velocityAvailable.toAmount(),
+ velocity = velocityAvailable,
canChangeScene = canChangeScene
)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
index 824c10b..a5fd1bf 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
@@ -16,10 +16,12 @@
package com.android.compose.nestedscroll
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
+import com.android.compose.ui.util.SpaceVectorConverter
/**
* This [NestedScrollConnection] waits for a child to scroll ([onPreScroll] or [onPostScroll]), and
@@ -147,3 +149,35 @@
return onStop(velocity)
}
}
+
+fun PriorityNestedScrollConnection(
+ orientation: Orientation,
+ canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
+ canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
+ canStartPostFling: (velocityAvailable: Float) -> Boolean,
+ canContinueScroll: () -> Boolean,
+ onStart: () -> Unit,
+ onScroll: (offsetAvailable: Float) -> Float,
+ onStop: (velocityAvailable: Float) -> Float,
+) =
+ with(SpaceVectorConverter(orientation)) {
+ PriorityNestedScrollConnection(
+ canStartPreScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset ->
+ canStartPreScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat())
+ },
+ canStartPostScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset ->
+ canStartPostScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat())
+ },
+ canStartPostFling = { velocityAvailable: Velocity ->
+ canStartPostFling(velocityAvailable.toFloat())
+ },
+ canContinueScroll = canContinueScroll,
+ onStart = onStart,
+ onScroll = { offsetAvailable: Offset ->
+ onScroll(offsetAvailable.toFloat()).toOffset()
+ },
+ onStop = { velocityAvailable: Velocity ->
+ onStop(velocityAvailable.toFloat()).toVelocity()
+ },
+ )
+ }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/SpaceVectorConverter.kt b/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/SpaceVectorConverter.kt
new file mode 100644
index 0000000..a13e944
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/SpaceVectorConverter.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.ui.util
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.unit.Velocity
+
+interface SpaceVectorConverter {
+ fun Offset.toFloat(): Float
+ fun Velocity.toFloat(): Float
+ fun Float.toOffset(): Offset
+ fun Float.toVelocity(): Velocity
+}
+
+fun SpaceVectorConverter(orientation: Orientation) =
+ when (orientation) {
+ Orientation.Horizontal -> HorizontalConverter
+ Orientation.Vertical -> VerticalConverter
+ }
+
+private val HorizontalConverter =
+ object : SpaceVectorConverter {
+ override fun Offset.toFloat() = x
+ override fun Velocity.toFloat() = x
+ override fun Float.toOffset() = Offset(this, 0f)
+ override fun Float.toVelocity() = Velocity(this, 0f)
+ }
+
+private val VerticalConverter =
+ object : SpaceVectorConverter {
+ override fun Offset.toFloat() = y
+ override fun Velocity.toFloat() = y
+ override fun Float.toOffset() = Offset(0f, this)
+ override fun Float.toVelocity() = Velocity(0f, this)
+ }