はじめに
こんにちは。新卒2年目のAndroidアプリエンジニアやってます。
なぐも@southcloud_7960というハンドルネームで活動しているものです。
今回は個人開発をしているアプリにアニメーションを導入してみたので、その経緯とできあがりについて紹介の記事を書こうと思います。
リリースしたアプリがこちらになります!
この記事の対象
- AndroidアプリやiOSアプリを開発している人
- 個人開発をしている人
- アニメーションを使ったアプリの開発に興味がある人
開発しているアプリ
私が開発している種族値クイズ(1.1.0)のアプリがこんな感じです。
今回は詳細な説明を省きますが、以下のような基本機能を備えています。
- 問題の出題範囲を選ぶ
- 問題が出題される
- 入力して回答する
- ボタンを押して次の問題に進む
- ギブアップして答えを表示する
アプリ開発の詳しい経緯については、また別の記事でご紹介したいと思います!
開発しているアプリに関する悩み
リリースするために最低限の機能を詰め込んだので、ちょっと画面が寂しいです。
表示する種族値は文字だけですし、入力、正解の表示とアプリを使う流れが淡々としています。
そこでアニメーションを導入することにしました!
アニメーションの導入
グラフの実装
@Composable
fun BaseStatsBarComponent(modifier: Modifier) {
Canvas(modifier = modifier) {
drawRect(
color = Pink,
topLeft = Offset(0f, 0f),
size = size
)
}
}
まずはCanvasを使って、グラフを実装しました。
簡単な図形の描画にはCanvasがシンプルで使いやすいです。
フラグでアニメーションを管理する
@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にするようなコードの場合…
@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の管理だと上手くいきませんでした。
そこで、表示する種族値のバーの値を監視し、値が変更された時に変更された分だけアニメーションするようにします。
@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を追加します。
dependencies {
implementation "com.airbnb.android:lottie-compose:$lottieVersion"
}
そして、使いたいComposableの中で呼び出します。
val composition by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.animation_cerebration)
)
LottieAnimation(
composition = composition,
)
これだけで正解画面にお祝いのアニメーションを追加することができました!
あまりのお手軽さにびっくりしました。
さいごに
ここまで読んでいただきありがとうございました。
無事アプリにアニメーションが追加できました。
アニメーションを追加したバージョンでぜひ遊んでみてください。感想などいただけますと嬉しいです!