Skip to content

Instantly share code, notes, and snippets.

@drampelt
Last active August 6, 2021 14:11
Show Gist options
  • Save drampelt/eba8384a5a89b6974bc2c998559c9577 to your computer and use it in GitHub Desktop.
Save drampelt/eba8384a5a89b6974bc2c998559c9577 to your computer and use it in GitHub Desktop.
@Composable
fun scroll2d() {
val offset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
Box(
modifier = modifier
.pointerInput(Unit) {
coroutineScope {
while (true) {
val pointerId = awaitPointerEventScope {
awaitFirstDown().id
}
val velocityTracker = VelocityTracker()
awaitPointerEventScope {
drag(pointerId) {
launch {
val change = it.positionChange()
offset.snapTo(Offset(
(offset.value.x + change.x).coerceIn(-maxWidth.toFloat() + width, 0f),
(offset.value.y + change.y).coerceIn(-maxHeight.toFloat() + height, 0f)
))
}
velocityTracker.addPosition(it.uptimeMillis, it.position)
}
}
val (x, y) = velocityTracker.calculateVelocity()
offset.updateBounds(
Offset(-maxWidth.toFloat() + width, -maxHeight.toFloat() + height),
Offset(0f, 0f)
)
launch {
var startVelocity = Offset(x, y)
do {
val result = offset.animateDecay(startVelocity, exponentialDecay())
startVelocity = result.endState.velocity
with(offset) {
if (value.x == upperBound?.x || value.x == lowerBound?.x) {
startVelocity = startVelocity.copy(x = 0f)
}
if (value.y == upperBound?.y || value.y == lowerBound?.y) {
startVelocity = startVelocity.copy(y = 0f)
}
}
} while (result.endReason == AnimationEndReason.BoundReached)
}
}
}
}
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment