0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Composeでカスタムのなんちゃってクロスフェードを作る

Posted at

経緯

現在アプリでいろんなViewをComposeに置き換え中です。

その中で、アニメーションで子要素の表示が切り替わるCrossFadeViewという内製のカスタムViewGroupがありました。そしてComposeにはもともとCrossfadeが備わっています。

ただ、内製のCrossFadeViewは実際はクロスフェードせず、前のViewが完全にフェードアウトしてから次のViewがフェードインするという、"嘘CrossFade" だったのです……なんとまあ……。1

クロスフェード 嘘クロスフェード2
スクリーンショット 2023-09-27 16.27.44.png スクリーンショット 2023-09-27 16.28.00.png

そうなると、正解の動きをするComposeのCrossfadeは使えませんね(トホホ)

カスタムのAnimetionで作ろう編

実現したいのは 表示→fadeout→fadein→表示→fadeout→fadein… という風に時間経過で表示が切り替わっていくアニメーションです。

今回のような要件を満たすカスタムのAnimationを作るにあたり、大きく分けてAnimatable
と、AnimatedContentを使う方法の2通りを比較しました。

特にAnimatedContentはやりたいことがそのまま簡単に実現できそうでしたが、少々怖い注意書きが…。

スクリーンショット 2023-09-27 16.32.16.png

ので、Animatableを使って実装することにしました。

早速ですがこんな感じ。

@Composable
fun MyCrossFadeIndexed(
    size: Int,
    content: @Composable (Int) -> Unit,
) {
    var index by remember { mutableStateOf(0) }
    val alpha = remember { Animatable(1f) }

    LaunchedEffect(key1 = alpha) {
        while (true) {
            delay(4000)
            alpha.animateTo(targetValue = 0f,animationSpec = tween(durationMillis = 300))
            index = (index + 1) % size
            alpha.animateTo(targetValue = 1f,animationSpec = tween(durationMillis = 300))
        }
    }

    Box(modifier = Modifier.alpha(alpha.value)) {
        content(index)
    }
}

こちらがアニメーションの本体です。

アニメーション部分
    var index by remember { mutableStateOf(0) }
    val alpha = remember { Animatable(1f) }

    LaunchedEffect(key1 = alpha) {
        while (true) {
            delay(4000)
            alpha.animateTo(targetValue = 0f,animationSpec = tween(durationMillis = 300))
            index = (index + 1) % size
            alpha.animateTo(targetValue = 1f,animationSpec = tween(durationMillis = 300))
        }
    }

AnimatableのalphaをBoxのModifier.alphaに入れて、
4秒表示したら0.3秒かけてfadeout、完全に消えたタイミングで表示するViewを切り替えて次のViewをまた0.3秒かけてfadeinさせるという方法になります。
(contentはindexを受け取って、何を表示させるかを選択する想定です)

余談

このあとコードレビューで「Composableの可変長引数(vararg)を引数に取ればいいんじゃない?」とのご指摘が……かっこよすぎる。

  1. 実はこのCustomViewGroupは自分が作っている。

  2. fade through というらしい

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?