Reputation: 677
In Android View System, We can use animation listener like below to get lottie animation callbacks.
playView = LottieAnimationView(this)
playView.addAnimatorListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
}
override fun onAnimationCancel(animation: Animator?) {
}
override fun onAnimationRepeat(animation: Animator?) {
}
})
How we can add listener using Jetpack Compose? i added below code currently to play the lottie animation. I want to receive the callback after animation play completed.
@Composable
fun PlayView() {
val animationSpec = remember { LottieAnimationSpec.RawRes(R.raw.play_anim) }
val result: LottieCompositionResult by remember { mutableStateOf(LottieCompositionResult.Loading) }
val context = LocalContext.current
LottieAnimation(
animationSpec,
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
)
if (result is LottieCompositionResult.Success) {
//start the next flow
}
}
Upvotes: 12
Views: 9218
Reputation: 1
I use next solution
private enum class LottieAnimationState {
PENDING, STARTED, PLAYING, ENDED
}
@Composable
fun ObserveLottieAnimationState(
progress: Float,
onStarted: () -> Unit = {},
onPlaying: (Float) -> Unit = {},
onEnded: () -> Unit = {}
) {
var state by remember { mutableStateOf(LottieAnimationState.PENDING) }
var wasStarted by remember { mutableStateOf(false) }
LaunchedEffect(progress) {
val newState = when {
progress == 0f -> LottieAnimationState.PENDING
progress > 0f && progress < 1f && !wasStarted -> {
wasStarted = true
LottieAnimationState.STARTED
}
progress > 0f && progress < 1f -> LottieAnimationState.PLAYING
progress == 1f -> LottieAnimationState.ENDED
else -> LottieAnimationState.PENDING
}
if (newState != state) {
state = newState
when (state) {
LottieAnimationState.PENDING -> {}
LottieAnimationState.STARTED -> onStarted()
LottieAnimationState.PLAYING -> onPlaying(progress)
LottieAnimationState.ENDED -> onEnded()
}
}
}
}
In UI
val progress by animateLottieCompositionAsState(
composition = composition,
iterations = 1,
isPlaying = true,
restartOnPlay = false
)
ObserveLottieAnimationState(progress, onStarted = {
Log.d("CheckLottieProgress", "onStarted")
}, onPlaying = {
Log.d("CheckLottieProgress", "onPlaying")
}, onEnded = {
Log.d("CheckLottieProgress", "onEnded")
})
My Logs:
D onStarted
D onPlaying
D onEnded
Upvotes: 0
Reputation: 5298
I was able to achieve this using the LottieAnimationState
returned by animateLottieCompositionAsState()
. In this case, I play the animation 3 times, then hide it, but you could put anything in the block where isAnimationVisible
is set to false.
Note that I was using lottie-compose v6.4.0 here.
var isAnimationVisible by remember { mutableStateOf(true) }
if (isAnimationVisible) {
val composition by rememberLottieComposition(LottieCompositionSpec.Asset("animation.json"))
val animationState = animateLottieCompositionAsState(
composition = composition,
iterations = 3
)
LaunchedEffect(animationState.progress) {
if (animationState.progress == 1f) {
// Animation finished
isAnimationVisible = false
}
}
composition?.also {
LottieAnimation(
composition = it,
progress = { animationState.progress },
)
}
}
Upvotes: 2
Reputation: 1659
You can use animatable isAtEnd/isPlaying/progress for that (6.4.0v)
val composition by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.your_lottie_file)
)
var shouldPlayAnimation by remember { mutableStateOf(false) }
val animatable = rememberLottieAnimatable()
LaunchedEffect(composition, shouldPlayAnimation) {
if (composition == null || !shouldPlayAnimation) return@LaunchedEffect
animatable.animate(composition, iteration = 1)
}
LottieAnimation(
composition = composition,
progress = { animatable.progress },
modifier = Modifier
.size(300.dp, 200.dp)
)
LaunchedEffect(animatable.isAtEnd) {
if (animatable.isAtEnd) {
shouldPlayAnimation = false
animatable.resetToBeginning()
}
Upvotes: 1
Reputation: 23984
Updated answer to version 1.0.0-rc01-1
of Lottie.
What you can do is:
val composition by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.your_lottie_file)
)
val progress by animateLottieCompositionAsState(composition)
LottieAnimation(
composition,
modifier = Modifier
.size(200.dp)
.background(Color.Black),
)
if (progress == 1.0f) {
// Animation completes.
}
Upvotes: 28