📱

Jetpack ComposeでLottieだけでボタンを作る

に公開

Lottieの公式のサンプルアニメーションをてきとうに取ってくる
https://lottiefiles.com/jp/free-animations/sample-ui

一番最初のフレームと最後のフレームを使って状態を表す
progressのrestartOnPlayでアニメーションが最初からスタートするようにする
OFF→ONになった時だけアニメーションをつけたいのでEnumで状態を管理する

private enum class AnimationState {
    IDLE,
    PLAYING,
    COMPLETED,
}

@Composable
fun LikeButton(
    modifier: Modifier = Modifier,
) {
    var isLiked by remember { mutableStateOf(false) }

    var animationState by remember { mutableStateOf(AnimationState.IDLE) }
    var displayProgress by remember  { mutableFloatStateOf(0f) }
    val composition by rememberLottieComposition(
        LottieCompositionSpec.RawRes(R.raw.heart_animation),
    )

    val progress by animateLottieCompositionAsState(
        composition = composition,
        isPlaying = animationState == AnimationState.PLAYING,
        iterations = 1,
        speed = 1f,
        restartOnPlay = true,
    )

    LaunchedEffect(progress, animationState, isLiked) {
        displayProgress = when (animationState) {
            AnimationState.PLAYING -> {
                if (progress == 1f) {
                    animationState = AnimationState.COMPLETED
                }
                progress
            }
            AnimationState.COMPLETED -> 1f
            AnimationState.IDLE -> if (isLiked) 1f else 0f
        }
    }

    Box(
        modifier = modifier,
        contentAlignment = Alignment.Center,
    ) {
        LottieAnimation(
            modifier = Modifier
                .size(128.dp)
                .clickable {
                    animationState = if (isLiked) AnimationState.IDLE else AnimationState.PLAYING
                    isLiked = !isLiked
                },
            composition = composition,
            progress = { displayProgress },
        )
    }
}

Discussion