Skip to content

Instantly share code, notes, and snippets.

@Ahmed-Sellami
Created September 18, 2021 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ahmed-Sellami/382a5c44b4a8f3785de823ccf9e76354 to your computer and use it in GitHub Desktop.
Save Ahmed-Sellami/382a5c44b4a8f3785de823ccf9e76354 to your computer and use it in GitHub Desktop.
fun Modifier.swipeToDelete(
offsetX: Animatable<Float, AnimationVector1D>,
maximumWidth: Float,
onDeleted: () -> Unit
): Modifier = composed {
pointerInput(Unit) {
// Used to calculate a settling position of a fling animation.
val decay = splineBasedDecay<Float>(this)
// Wrap in a coroutine scope to use suspend functions for touch events and animation.
coroutineScope {
while (true) {
// Wait for a touch down event.
val pointerId = awaitPointerEventScope { awaitFirstDown().id }
// Interrupt any ongoing animation of other items.
offsetX.stop()
// Prepare for drag events and record velocity of a fling.
val velocityTracker = VelocityTracker()
// Wait for drag events.
awaitPointerEventScope {
horizontalDrag(pointerId) { change ->
if (change.positionChange().x > 0 || offsetX.value > 0f) {
val horizontalDragOffset = offsetX.value + change.positionChange().x
launch {
offsetX.snapTo(horizontalDragOffset)
}
// Record the velocity of the drag.
velocityTracker.addPosition(change.uptimeMillis, change.position)
// Consume the gesture event, not passed to external
change.consumePositionChange()
}
}
}
// Dragging finished. Calculate the velocity of the fling.
var velocity = velocityTracker.calculateVelocity().x
// Calculate the eventual position where the fling should settle
// based on the current offset value and velocity
val targetOffsetX = decay.calculateTargetValue(offsetX.value, velocity)
// Set the upper and lower bounds so that the animation stops when it
// reaches the edge.
offsetX.updateBounds(
lowerBound = 0f,
upperBound = size.width.toFloat()
)
launch {
// Slide back the element if the settling position does not go beyond
// the size of the element. Remove the element if it does.
if (targetOffsetX.absoluteValue <= maximumWidth) {
// Not enough velocity; Slide back.
offsetX.animateTo(targetValue = 0f, initialVelocity = velocity)
} else {
if (velocity >= 0f) {
// If the velocity is low, we create a fake velocity to make the animation look smoother
if (velocity <= 500f) {
velocity = 2000f
}
// Enough velocity to slide away the element to the edge.
offsetX.animateDecay(velocity, decay)
// The element was swiped away.
onDeleted()
}
}
}
}
}
}
.offset {
// Use the animating offset value here.
IntOffset(offsetX.value.roundToInt(), 0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment