Skip to content

Instantly share code, notes, and snippets.

@sergenes
Last active July 3, 2021 16:20
Show Gist options
  • Save sergenes/81b399115e5734f39ff9d9f91adadc39 to your computer and use it in GitHub Desktop.
Save sergenes/81b399115e5734f39ff9d9f91adadc39 to your computer and use it in GitHub Desktop.
data class CardSwipeAnimation(
val model: StudyCardDeckModel,
val cardWidth: Float,
val cardHeight: Float
) {
private lateinit var cardDragOffset: Animatable<Offset, AnimationVector2D>
@Composable
fun Init() {
cardDragOffset = remember {
Animatable(
targetValueByState(CardSwipeState.INITIAL),
Offset.VectorConverter,
)
}
}
private fun targetValueByState(state: CardSwipeState): Offset {
return when (state) {
CardSwipeState.INITIAL -> {
Offset(0F, paddingOffset)
}
CardSwipeState.SWIPED -> {
Offset(model.screenWidth.toFloat() + cardWidth, paddingOffset)
}
else -> {
swipeDirection()
}
}
}
private val animationSpec: FiniteAnimationSpec<Offset> = tween(
durationMillis = animationTime,
easing = FastOutLinearInEasing
)
private fun swipeDirection(): Offset {
val halfW = model.screenWidth / 2f
val halfH = model.screenHeight / 2f
val x = when {
cardDragOffset.value.x > halfW -> model.screenWidth.toFloat()
cardDragOffset.value.x + cardWidth < halfW -> -cardWidth
else -> 0f
}
val y = when {
cardDragOffset.value.y > halfH -> model.screenHeight.toFloat()
cardDragOffset.value.y + cardHeight < halfH -> -cardHeight
else -> 0f
}
return Offset(x, y)
}
fun animateToTarget(
coroutineScope: CoroutineScope,
state: CardSwipeState,
finishedCallback: (Boolean) -> Unit
) {
coroutineScope.launch {
val target = targetValueByState(state)
cardDragOffset.animateTo(
targetValue = target,
animationSpec = animationSpec,
block = {
if (value.x == targetValue.x &&
value.y == targetValue.y
) {
val next = !(targetValue.x == 0f && targetValue.y == 0f)
finishedCallback(next)
}
}
)
}
}
fun toIntOffset(): IntOffset {
return IntOffset(
cardDragOffset.value.x.toInt(),
cardDragOffset.value.y.toInt()
)
}
fun backToInitialState(coroutineScope: CoroutineScope) {
snapTo(coroutineScope, targetValueByState(CardSwipeState.INITIAL))
}
private fun snapTo(coroutineScope: CoroutineScope, target: Offset) {
coroutineScope.launch {
cardDragOffset.snapTo(target)
}
}
fun draggingCard(
coroutineScope: CoroutineScope,
change: PointerInputChange,
callBack: () -> Unit
) {
if (change.pressed) {
val original =
Offset(
cardDragOffset.value.x,
cardDragOffset.value.y
)
val summed = original + change.positionChange()
val newValue = Offset(
x = summed.x,
y = summed.y
)
change.consumePositionChange()
snapTo(coroutineScope, Offset(newValue.x, newValue.y))
callBack()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment