はじめに
私はダークモード機能が出る前からアニメーション部分は掲題のLottieを使っていました。
プロダクト開発でダークモード対応するにあたり対応時調べたことを整理します
Lottie導入手順(without compose)
前準備としてBuild.gradle(app)に以下を追加
dependencies {
implementation 'com.airbnb.android:lottie:$lottieVersion'
}
Before(ダークモード対応:ひと手間必要)
- アニメーションするJson(ここではlike_animation.json, like_animation_dark.jsonを使うとします)をassetsディレクトリに階層を掘って置く(app/src/main/assets/lottie)
2-1. アニメーションさせたい箇所にXMLで埋め込む
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/likeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName=“lottie/like_anumation.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
上記は見て分かる通りダークモード用とライトモード用のJsonを分けて保存できないため、MVVMでViewModelでダークモードか判定して、渡すJsonを切り替えるかViewを2つ用意してVisibilityでライトかダークかで切り替える等の対応になるかと思います
※MVVMでやるなら以下のようになる(ViewModelでダークモード判定用メソッドがある前提)
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/likeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName=“@{viewModel.isDarkMode ? lottie/like_anumation_dark.json : lottie/like_anumation.json}"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
2-2. 動的に表示させたい場合は以下な感じです
assets.open(“lottie/like_anumation.json”).use { inputStream ->
val lottieResult: LottieResult<LottieComposition> =
LottieCompositionFactory.fromJsonInputStreamSync(
inputStream,
"like_anumation.json"
)
LottieDrawable().apply {
composition = lottieResult.value
repeatCount = LottieDrawable.INFINITE
addAnimatorListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
binding.likeView = ResourcesCompat.getDrawable(
resources,
R.drawable.like_normal,
null
)
}
})
}.playAnimation()
上記動的対応版も同様に、ネイティブコード側でダークモードかどうかの判定を入れる必要があります
After(ダークモード対応:楽)
- アニメーションするJson(ここではlike_animation.jsonを使うとします)をrawディレクトリ、raw-nightディレクトリに置く(app/src/main/res/raw and app/src/main/res/raw-night)
※公式ドキュメントには特にダークモード対応として記載がないですがソースに実装がありました
2-1. アニメーションさせたい箇所にXMLで埋め込む
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/likeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_rawRes=“like_anumation.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
2-2. 動的に表示させたい場合は以下な感じです
val lottieResult: LottieResult<LottieComposition> =
LottieCompositionFactory.fromRawResSync(
this@MainActivity,
R.raw.like_animation
)
LottieDrawable().apply {
composition = lottieResult.value
repeatCount = LottieDrawable.INFINITE
addAnimatorListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
binding.likeView = ResourcesCompat.getDrawable(
resources,
R.drawable.like_normal,
null
)
}
})
}.playAnimation()
colorのダークモード対応等と同様にnight用のディレクトリに同名Jsonを置くだけでXMLでも動的対応版でもよしなにやってくれました
まとめ
あまり意識せず公式の手順通り app:lottie_rawRes
を使っていればはまらなかった問題でした
もしもLottieを使っていて、同じような問題に当たってしまった方の参考になったら幸いです