Skip to content

Commit

Permalink
#6 - Gesture animation
Browse files Browse the repository at this point in the history
  • Loading branch information
jhg3410 committed Feb 18, 2023
1 parent ee0e56b commit 15ab0d5
Showing 1 changed file with 20 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ import com.example.android.codelab.animation.ui.*
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.math.absoluteValue
import kotlin.math.roundToInt

private enum class TabPage {
Home, Work
Expand Down Expand Up @@ -599,6 +601,7 @@ private fun Modifier.swipeToDismiss(
onDismissed: () -> Unit
): Modifier = composed {
// TODO 6-1: Create an Animatable instance for the offset of the swiped element.
val offsetX = remember { Animatable(0f) }
pointerInput(Unit) {
// Used to calculate a settling position of a fling animation.
val decay = splineBasedDecay<Float>(this)
Expand All @@ -608,12 +611,17 @@ private fun Modifier.swipeToDismiss(
// Wait for a touch down event.
val pointerId = awaitPointerEventScope { awaitFirstDown().id }
// TODO 6-2: Touch detected; the animation should be stopped.
offsetX.stop()
// Prepare for drag events and record velocity of a fling.
val velocityTracker = VelocityTracker()
// Wait for drag events.
awaitPointerEventScope {
horizontalDrag(pointerId) { change ->
// TODO 6-3: Apply the drag change to the Animatable offset.
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
Expand All @@ -624,18 +632,29 @@ private fun Modifier.swipeToDismiss(
val velocity = velocityTracker.calculateVelocity().x
// TODO 6-4: Calculate the eventual position where the fling should settle
// based on the current offset value and velocity
val targetOffsetX = decay.calculateTargetValue(offsetX.value, velocity)
// TODO 6-5: Set the upper and lower bounds so that the animation stops when it
// reaches the edge.
offsetX.updateBounds(
lowerBound = -size.width.toFloat(),
upperBound = size.width.toFloat()
)
launch {
// TODO 6-6: 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 <= size.width) {
offsetX.animateTo(targetValue = 0f, initialVelocity = velocity)
} else {
offsetX.animateDecay(velocity, decay)
onDismissed()
}
}
}
}
}
.offset {
// TODO 6-7: Use the animating offset value here.
IntOffset(0, 0)
IntOffset(offsetX.value.roundToInt(), 0)
}
}

Expand Down

0 comments on commit 15ab0d5

Please sign in to comment.