1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人開発のAndroidアプリにアニメーションを導入してみた【種族値クイズ】

Posted at

はじめに

こんにちは。新卒2年目のAndroidアプリエンジニアやってます。
なぐも@southcloud_7960というハンドルネームで活動しているものです。
今回は個人開発をしているアプリにアニメーションを導入してみたので、その経緯とできあがりについて紹介の記事を書こうと思います。

リリースしたアプリがこちらになります!

この記事の対象

  • AndroidアプリやiOSアプリを開発している人
  • 個人開発をしている人
  • アニメーションを使ったアプリの開発に興味がある人

開発しているアプリ

私が開発している種族値クイズ(1.1.0)のアプリがこんな感じです。
今回は詳細な説明を省きますが、以下のような基本機能を備えています。

  • 問題の出題範囲を選ぶ
  • 問題が出題される
  • 入力して回答する
  • ボタンを押して次の問題に進む
  • ギブアップして答えを表示する

アプリ開発の詳しい経緯については、また別の記事でご紹介したいと思います!

開発しているアプリに関する悩み

リリースするために最低限の機能を詰め込んだので、ちょっと画面が寂しいです。
表示する種族値は文字だけですし、入力、正解の表示とアプリを使う流れが淡々としています。

そこでアニメーションを導入することにしました!

アニメーションの導入

グラフの実装

BaseStatsRowComponent.kt
@Composable
fun BaseStatsBarComponent(modifier: Modifier) {
    Canvas(modifier = modifier) {
        drawRect(
            color = Pink,
            topLeft = Offset(0f, 0f),
            size = size
        )
    }
}

まずはCanvasを使って、グラフを実装しました。
簡単な図形の描画にはCanvasがシンプルで使いやすいです。

フラグでアニメーションを管理する

BaseStatsBarComponent.kt
@Composable
fun BaseStatsBarComponent(modifier: Modifier) {
    val animationFlag = remember { mutableStateOf(false) }
    val animateWidth by animateFloatAsState(targetValue = if (animationFlag.value) 1f else 0f)

    Canvas(modifier = modifier) {
        animationFlag.value = true
        drawRect(
            color = Pink,
            topLeft = Offset(0f, 0f),
            size = Size(width = size.width * animateWidth, height = size.height)
        )
    }
}

animationFlagとanimateFloatAsStateを使ってアニメーションを管理します。
コンポーズされたタイミングでanimationFlagがfalseからtrueになり、
animateWidthで設定しているtargetの値が変更されることでアニメーションが走ります。

これでグラフがアニメーションするようになりました!

ただ、こちらのアニメーションの管理だと、次の問題へ進んだ時にアニメーションしてくれません。
falseがtrueになった時アニメーションするので、初回コンポーズ以降にアニメーションするタイミングがないからです。
trueになったまま変わりません。

かといって、一度falseにするようなコードの場合…

BaseStatsBarComponent.kt
@Composable
fun BaseStatsBarComponent(modifier: Modifier) {
    val animationFlag = remember { mutableStateOf(false) }
    val animateWidth by animateFloatAsState(targetValue = if (animationFlag.value) 1f else 0f)

    Canvas(modifier = modifier) {
        animationFlag.value = true
        drawRect(
            color = Pink,
            topLeft = Offset(0f, 0f),
            size = Size(width = size.width * animateWidth, height = size.height)
        )
    }
    animationFlag.value = false
}

このように、ノリノリのグラフになってしまいました。
アニメーションは値の変更を少しずつ反映させるため、多分その時にtrue-falseの変更を繰り返しちゃっていますね。
また、falseにするとそれに対応してグラフが0になるようにアニメーションされてしまうため、上手くいきません。

アニメーションする値を監視する

true-falseの管理だと上手くいきませんでした。
そこで、表示する種族値のバーの値を監視し、値が変更された時に変更された分だけアニメーションするようにします。

StatsRowComponent.kt
@Composable
fun StatRowComponent(label: String, value: String) {
    var animatedValue by remember { mutableStateOf(0f) }

    LaunchedEffect(value) {
        // 画面幅に収まるようにサイズを0.8倍に調整
        animatedValue = (value.toFloat() * 0.8).toFloat()
    }

    val animation by animateFloatAsState(
        targetValue = animatedValue,
    )
        // 省略
        
        BaseStatsBarComponent(
            modifier = Modifier
                .width(animation.dp)
                .height(50.dp),
        )
        
        // 省略
}

LaunchedEffectで受け取る種族値の値を監視し、値が変わった時にanimationValueが変更されることでアニメーションされるようにします。
こうすることで、次の問題へ進んだ時にもアニメーションしてくれるようになりました。

Lottieを使い、さらに豪華にする

これで出題はアニメーションされるようになりましたが、もう一味加えたいです。

アニメーションを使う目的の1つに、「ユーザー体験のゴールを彩る」というものがあると勝手に思っています。
私の作った種族値クイズのアプリの場合、ユーザー体験のゴールは「クイズに答えて正解する」ことです。

特にこの種族値クイズは選択肢などがなく、割と難易度が高めに設定されているため、正解した時の演出ももう少し豪華にしたいと考えました。

そこで今回使うのが、Lottieというサービスです。

Lottieとは

Lottieは、JSONベースのアニメーションファイル形式です。iOSやAndroidでも簡単に使うことができ、アニメーションファイルを作ったり見つけることができます。

特にアニメーションがたくさんあり、「なんかお祝いしてる感じのアニメーション」をすぐに見つけることができました。
イメージと合って、良い感じ!

Lottieの導入

Littieを使うまでもすごく簡単です。
まずはimplementationを追加します。

build.gradle.kts
dependencies {
    implementation "com.airbnb.android:lottie-compose:$lottieVersion"
}

そして、使いたいComposableの中で呼び出します。

AnswerResultSection.kt
val composition by rememberLottieComposition(
        LottieCompositionSpec.RawRes(R.raw.animation_cerebration)
    )
    LottieAnimation(
        composition = composition,
    )

これだけで正解画面にお祝いのアニメーションを追加することができました!
あまりのお手軽さにびっくりしました。

さいごに

ここまで読んでいただきありがとうございました。
無事アプリにアニメーションが追加できました。

アニメーションを追加したバージョンでぜひ遊んでみてください。感想などいただけますと嬉しいです!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?