Last active
July 3, 2021 16:20
-
-
Save sergenes/81b399115e5734f39ff9d9f91adadc39 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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