aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-07-03 08:51:54 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-07-03 08:51:54 +0000
commit5e0b409da1f9aae82ed35ef41c6e1eb85770a86e (patch)
treecb5c03081f87de3eeea0d52c1767a303e1c5bd81
parent2ce6d70a98f101a1cf01385b8ee0236af8ed1434 (diff)
parent51bd5653e69bea874c324b6feceaae4b99c42d32 (diff)
downloadsupport-snap-temp-L55300030004920257.tar.gz
Merge "Merge cherrypicks of ['android-review.googlesource.com/3158416'] into androidx-compose-beta-release." into androidx-compose-beta-releasesnap-temp-L55300030004920257snap-temp-L14600030004918727
-rw-r--r--compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt37
-rw-r--r--compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt10
-rw-r--r--compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt21
3 files changed, 62 insertions, 6 deletions
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
index e6d37c8ffa1..e38b01c040e 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
@@ -204,6 +204,43 @@ class SnapFlingBehaviorTest {
}
@Test
+ fun performFling_invalidOffsets_shouldNotPropagateNans_calculateSnapOffset() {
+ val testLayoutInfoProvider =
+ object : SnapLayoutInfoProvider {
+ override fun calculateSnapOffset(velocity: Float): Float = Float.NaN
+ }
+ lateinit var testFlingBehavior: TargetedFlingBehavior
+ val exception =
+ kotlin.runCatching {
+ rule.setContent {
+ testFlingBehavior = rememberSnapFlingBehavior(testLayoutInfoProvider)
+ VelocityEffect(testFlingBehavior, TestVelocity)
+ }
+ }
+ assert(exception.isFailure)
+ }
+
+ @Test
+ fun performFling_invalidOffsets_shouldNotPropagateNans_calculateApproachOffset() {
+ val testLayoutInfoProvider =
+ object : SnapLayoutInfoProvider {
+ override fun calculateApproachOffset(velocity: Float, decayOffset: Float): Float =
+ Float.NaN
+
+ override fun calculateSnapOffset(velocity: Float): Float = 0.0f
+ }
+ lateinit var testFlingBehavior: TargetedFlingBehavior
+ val exception =
+ kotlin.runCatching {
+ rule.setContent {
+ testFlingBehavior = rememberSnapFlingBehavior(testLayoutInfoProvider)
+ VelocityEffect(testFlingBehavior, TestVelocity)
+ }
+ }
+ assert(exception.isFailure)
+ }
+
+ @Test
fun findClosestOffset_noFlingDirection_shouldReturnAbsoluteDistance() {
val testLayoutInfoProvider = TestLayoutInfoProvider()
val offset = testLayoutInfoProvider.calculateSnapOffset(0f)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
index f33de5c766b..335eedc8769 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
@@ -77,6 +77,9 @@ internal fun SnapLayoutInfoProvider(
debugLog { "Approach Velocity=$velocity" }
val effectivePageSizePx = pagerState.pageSize + pagerState.pageSpacing
+ // Page Size is Zero, do not proceed.
+ if (effectivePageSizePx == 0) return 0f
+
// given this velocity, where can I go with a decay animation.
val animationOffsetPx = decayOffset
@@ -246,8 +249,13 @@ internal fun calculateFinalSnappingBound(
"layoutDirection=$layoutDirection"
}
// how many pages have I scrolled using a drag gesture.
+ val pageSize = pagerState.layoutInfo.pageSize
val offsetFromSnappedPosition =
- pagerState.dragGestureDelta() / pagerState.layoutInfo.pageSize.toFloat()
+ if (pageSize == 0) {
+ 0f
+ } else {
+ pagerState.dragGestureDelta() / pageSize.toFloat()
+ }
// we're only interested in the decimal part of the offset.
val offsetFromSnappedPositionOverflow =
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
index d4134b62c7b..3956b6f9cad 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
@@ -127,10 +127,15 @@ class SnapFlingBehavior(
initialValue = 0.0f
)
- val initialOffset =
- snapLayoutInfoProvider.calculateApproachOffset(initialVelocity, decayOffset)
- var remainingScrollOffset =
- abs(initialOffset) * sign(initialVelocity) // ensure offset sign is correct
+ val initialOffset =
+ snapLayoutInfoProvider.calculateApproachOffset(initialVelocity, decayOffset)
+
+ check(!initialOffset.isNaN()) {
+ "calculateApproachOffset returned NaN. Please use a valid value."
+ }
+
+ // ensure offset sign and value are correct
+ var remainingScrollOffset = abs(initialOffset) * sign(initialVelocity)
onRemainingScrollOffsetUpdate(remainingScrollOffset) // First Scroll Offset
@@ -142,9 +147,15 @@ class SnapFlingBehavior(
onRemainingScrollOffsetUpdate(remainingScrollOffset)
}
- remainingScrollOffset =
+ val finalSnapOffset =
snapLayoutInfoProvider.calculateSnapOffset(animationState.velocity)
+ check(!finalSnapOffset.isNaN()) {
+ "calculateSnapOffset returned NaN. Please use a valid value."
+ }
+
+ remainingScrollOffset = finalSnapOffset
+
debugLog { "Settling Final Bound=$remainingScrollOffset" }
animateWithTarget(