Fix scroll animation when system animation is disabled (#7509)
parent
788583e66f
commit
ba93060e59
@ -0,0 +1,60 @@
|
||||
package eu.kanade.presentation.util
|
||||
|
||||
import androidx.compose.animation.core.AnimationState
|
||||
import androidx.compose.animation.core.DecayAnimationSpec
|
||||
import androidx.compose.animation.core.animateDecay
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.gestures.FlingBehavior
|
||||
import androidx.compose.foundation.gestures.ScrollScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.MotionDurationScale
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* FlingBehavior that always uses the default motion scale.
|
||||
*
|
||||
* This makes the scrolling animation works like View's lists
|
||||
* when "Remove animation" settings is on.
|
||||
*/
|
||||
@Composable
|
||||
fun flingBehaviorIgnoringMotionScale(): FlingBehavior {
|
||||
val flingSpec = rememberSplineBasedDecay<Float>()
|
||||
return remember(flingSpec) {
|
||||
DefaultFlingBehavior(flingSpec)
|
||||
}
|
||||
}
|
||||
|
||||
private val DefaultMotionDurationScale = object : MotionDurationScale {
|
||||
// Use default motion scale factor
|
||||
override val scaleFactor: Float = 1f
|
||||
}
|
||||
|
||||
private class DefaultFlingBehavior(
|
||||
private val flingDecay: DecayAnimationSpec<Float>,
|
||||
) : FlingBehavior {
|
||||
override suspend fun ScrollScope.performFling(initialVelocity: Float): Float {
|
||||
// come up with the better threshold, but we need it since spline curve gives us NaNs
|
||||
return if (abs(initialVelocity) > 1f) {
|
||||
var velocityLeft = initialVelocity
|
||||
var lastValue = 0f
|
||||
withContext(DefaultMotionDurationScale) {
|
||||
AnimationState(
|
||||
initialValue = 0f,
|
||||
initialVelocity = initialVelocity,
|
||||
).animateDecay(flingDecay) {
|
||||
val delta = value - lastValue
|
||||
val consumed = scrollBy(delta)
|
||||
lastValue = value
|
||||
velocityLeft = this.velocity
|
||||
// avoid rounding errors and stop if anything is unconsumed
|
||||
if (abs(delta - consumed) > 0.5f) this.cancelAnimation()
|
||||
}
|
||||
}
|
||||
velocityLeft
|
||||
} else {
|
||||
initialVelocity
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue