アニメーションとトランジションをComposeで実装する【Jetpack Compose入門⑮】

Jetpack Composeにおけるアニメーションの基本

Jetpack Composeのアニメーションとは?

Jetpack Composeでは、視覚的に魅力的なアニメーションを簡単に実装できます。XMLでのアニメーション定義が不要になり、Kotlinのコードのみで制御できるのが大きな特徴です。

Composeでアニメーションを実装する利点

  • シンプルな記述: 少ないコードで複雑なアニメーションを作成可能。
  • 状態に基づいたアニメーション: remembermutableStateOf を使用し、状態変更に応じてアニメーションを制御。
  • パフォーマンスの最適化: Jetpack Composeの再コンポーズと効率的に統合。

基本的なアニメーションの実装

animateFloatAsState を使用したシンプルなアニメーション

animateFloatAsState を使うことで、数値(例えば透明度やサイズなど)をアニメーションさせることができます。

@Composable
fun SimpleAnimation() {
    var expanded by remember { mutableStateOf(false) }
    val size by animateFloatAsState(targetValue = if (expanded) 200f else 100f)

    Box(
        modifier = Modifier
            .size(size.dp)
            .background(Color.Blue)
            .clickable { expanded = !expanded }
    )
}

animateDpAsState を使用したサイズの変化

animateDpAsState を使うと、Dp(密度独立ピクセル)の値を滑らかに変化させることができます。

@Composable
fun SizeAnimation() {
    var expanded by remember { mutableStateOf(false) }
    val size by animateDpAsState(targetValue = if (expanded) 150.dp else 50.dp)

    Box(
        modifier = Modifier
            .size(size)
            .background(Color.Green)
            .clickable { expanded = !expanded }
    )
}

トランジションを使ったアニメーション

updateTransition を使用した状態ごとのアニメーション

updateTransition は、複数のプロパティを連動させたアニメーションを実装するのに適しています。

@Composable
fun TransitionAnimation() {
    var isExpanded by remember { mutableStateOf(false) }
    val transition = updateTransition(targetState = isExpanded, label = "boxTransition")

    val size by transition.animateDp(label = "size") { state ->
        if (state) 200.dp else 100.dp
    }

    val color by transition.animateColor(label = "color") { state ->
        if (state) Color.Red else Color.Gray
    }

    Box(
        modifier = Modifier
            .size(size)
            .background(color)
            .clickable { isExpanded = !isExpanded }
    )
}

AnimatedVisibility を使った表示・非表示アニメーション

AnimatedVisibility を使用すると、要素の表示・非表示をアニメーションさせることができます。

@Composable
fun VisibilityAnimation() {
    var visible by remember { mutableStateOf(false) }

    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { visible = !visible }) {
            Text("切り替え")
        }
        AnimatedVisibility(visible = visible) {
            Box(
                modifier = Modifier
                    .size(100.dp)
                    .background(Color.Magenta)
            )
        }
    }
}

Crossfade を使った画面の切り替え

Crossfade を使用すると、異なるコンテンツ間をスムーズに遷移できます。

@Composable
fun CrossfadeExample() {
    var isFirstScreen by remember { mutableStateOf(true) }
    
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { isFirstScreen = !isFirstScreen }) {
            Text("画面切り替え")
        }
        
        Crossfade(targetState = isFirstScreen) { screen ->
            if (screen) {
                Box(modifier = Modifier.size(100.dp).background(Color.Cyan))
            } else {
                Box(modifier = Modifier.size(100.dp).background(Color.Yellow))
            }
        }
    }
}

まとめ

Jetpack Composeを活用すると、少ないコードでスムーズなアニメーションを実装できます。

  • 基本アニメーション: animateFloatAsStateanimateDpAsState を使用してシンプルなアニメーションを実装。
  • トランジション: updateTransition を利用して複数のプロパティを連動させる。
  • 表示・非表示のアニメーション: AnimatedVisibility を活用してスムーズに要素の出入りを実現。
  • 画面遷移: Crossfade を用いてコンテンツの切り替えを滑らかにする。

Jetpack Composeのアニメーションを活用して、より魅力的なUIを構築しましょう!