diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-07-03 08:51:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-07-03 08:51:54 +0000 |
commit | 5e0b409da1f9aae82ed35ef41c6e1eb85770a86e (patch) | |
tree | cb5c03081f87de3eeea0d52c1767a303e1c5bd81 | |
parent | 2ce6d70a98f101a1cf01385b8ee0236af8ed1434 (diff) | |
parent | 51bd5653e69bea874c324b6feceaae4b99c42d32 (diff) | |
download | support-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
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( |