Contents
アニメーションのカテゴリと公式ドキュメント
Compose のアニメーションは 4 つの大分類 に分かれます。公式ガイド(Android Developers – Compose Animation)では、各カテゴリごとのサンプルとベストプラクティスが網羅されています。
| カテゴリ | 主な API | 用途の例 |
|---|---|---|
| Visibility | AnimatedVisibility |
条件に応じた表示・非表示のフェードやスライド |
| State | animate*AsState(animateDpAsState など) |
単一プロパティの変化を自動補間 |
| Transition | updateTransition |
複数状態・複数プロパティを同時に遷移 |
| Infinite | rememberInfiniteTransition |
永続的なローディングやバウンスエフェクト |
単一プロパティのアニメーション
1. AnimatedVisibility で if 文を書き換える
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Composable fun GreetingCard(visible: Boolean) { AnimatedVisibility( visible = visible, enter = fadeIn(tween(300)), exit = fadeOut(tween(200)) ) { Card(modifier = Modifier.padding(16.dp)) { Text("Hello") } } } |
- 効果:条件分岐だけでフェードイン・アウトが自動付与され、コード量が約 30 % 削減。
- ポイント:
enter/exitに好きなアニメーション(スライドや拡大縮小)を組み合わせられる。
2. animate*AsState 系関数で単一プロパティを補間
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@Composable fun AnimatedBox(isExpanded: Boolean) { val size by animateDpAsState( targetValue = if (isExpanded) 200.dp else 100.dp, animationSpec = tween(400, easing = LinearOutSlowInEasing) ) val color by animateColorAsState( targetValue = if (isExpanded) Color(0xFF4CAF50) else Color(0xFFF44336), animationSpec = spring(stiffness = Spring.StiffnessLow) ) val alpha by animateFloatAsState( targetValue = if (isExpanded) 1f else 0.5f, animationSpec = tween(500) ) Box( Modifier .size(size) .background(color) .alpha(alpha) ) } |
- 利点:状態 (
isExpanded) が変わるたびに自動でアニメーションが走り、animationSpecを自由に差し替え可能。 - 公式サンプル:Compose Animation Samples – animate*AsState
複数状態遷移 – updateTransition
実装例:カードの 4 状態管理
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
enum class CardState { Idle, Loading, Success, Error } @Composable fun StatefulCard(state: CardState) { val transition = updateTransition(targetState = state, label = "CardTransition") // 背景色 val bgColor by transition.animateColor( transitionSpec = { when { CardState.Loading isTransitioningTo CardState.Success -> tween(500) else -> spring() } }, label = "bg" ) { s -> when (s) { CardState.Idle -> Color.LightGray CardState.Loading-> Color.Yellow CardState.Success-> Color(0xFF4CAF50) CardState.Error -> Color(0xFFF44336) } } // サイズ val size by transition.animateDp( transitionSpec = { spring(stiffness = Spring.StiffnessMedium) }, label = "size" ) { s -> when (s) { CardState.Idle -> 120.dp CardState.Loading-> 140.dp else -> 180.dp } } // 透明度 val alpha by transition.animateFloat( transitionSpec = { tween(300) }, label = "alpha" ) { s -> if (s == CardState.Loading) 0.6f else 1f } Box( Modifier .size(size) .background(bgColor) .alpha(alpha), contentAlignment = Alignment.Center ) { Text(state.name, color = Color.White) } } |
- ポイント
updateTransitionが状態遷移を検知し、各プロパティごとに別々のイージングやスプリングを設定できる。-
transitionSpecは「状態 A → 状態 B」だけに特化した仕様を書けるため、細かい UX チューニングが可能。 -
参考:公式ドキュメントの Transition API
無限・繰り返しアニメーション
1. rememberInfiniteTransition(永続的なエフェクト)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Composable fun PulsingCircle() { val infinite = rememberInfiniteTransition(label = "Pulse") val scale by infinite.animateFloat( initialValue = 0.8f, targetValue = 1.2f, animationSpec = infiniteRepeatable( animation = tween(800, easing = LinearEasing), repeatMode = RepeatMode.Reverse ), label = "scale" ) Box( Modifier .size(100.dp) .graphicsLayer(scaleX = scale, scaleY = scale) .background(Color.Cyan, shape = CircleShape) ) } |
- 備考:Compose 1.6 では内部実装が最適化され、CPU 使用率は従来と同程度かやや低減されています(公式リリースノート参照)。
2. repeatable で回数限定のアニメーション
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@Composable fun ShakeOnError(isError: Boolean) { val offsetX by rememberInfiniteTransition().animateFloat( initialValue = 0f, targetValue = if (isError) 16f else 0f, animationSpec = if (isError) repeatable( iterations = 3, animation = tween(100, easing = FastOutLinearInEasing), repeatMode = RepeatMode.Reverse ) else snap(), label = "shake" ) Box( Modifier .offset(x = offsetX.dp) .size(80.dp) .background(Color.Red, shape = RoundedCornerShape(8.dp)), contentAlignment = Alignment.Center ) { Text("Error", color = Color.White) } } |
iterationsで回数を明示でき、完了後は自動的に停止します。
3. デフォルト設定の変更点(Compose 1.6)
| Spec | 従来 (≤ 1.5) | 1.6 以降 |
|---|---|---|
tween のデフォルト duration |
300 ms | 250 ms(公式リリースで調整) |
spring のデフォルト dampingRatio |
MediumBouncy |
LowBouncy |
※ 必要に応じて旧バージョンと同等の挙動を保ちたい場合は、
animationSpec = tween(300)などと明示してください。
詳細は Compose 1.6 Release Notes を参照。
デバッグと Layout Inspector の活用法
Layout Inspector でアニメーションを可視化
公式ツールの Animation タブは、実行中の Transition のパラメータや現在のフレームをスローモーションで確認できます。手順は次の通りです。
- デバイス/エミュレータで対象アプリを起動
- Run > Attach debugger to Android Process でデバッグ接続
- メニュー View → Tool Windows → Layout Inspector を開く
- 左上の Refresh ボタンで UI ツリー取得
- 任意の Compose 要素を選択し、右ペインの Animation タブへ切替
- 「Play」ボタンでスローモーション再生、各アニメーションの
duration・easingが一覧表示される
デバッグ時のベストプラクティス
| 手法 | 内容 |
|---|---|
| State ログ | Log.d("Anim", "alpha=$alpha") で状態遷移を可視化 |
| テストタグ | Modifier.testTag("myBox") → Layout Inspector の検索に利用 |
| プレビューのスローモーション | Android Studio の「Preview」画面右上で速度調整可能 |
XML から Compose への移行チェックリスト
| 項目 | XML の書き方 | Compose への変換例 |
|---|---|---|
| 開始タイミング | animator.start() |
状態 (visible = true) が変化した瞬間に自動開始 |
| イージング | <interpolator> タグ |
tween(easing = ...) または spring |
| 繰り返し回数 | repeatCount 属性 |
infiniteRepeatable / repeatable(iterations = n) |
| キャンセル | animator.cancel() |
状態が変わらなくなると自動停止(例: visible = false) |
| スコープ管理 | AnimatorSet |
updateTransition で複数プロパティを同時遷移 |
実装サンプル比較
|
1 2 3 4 5 6 |
<objectAnimator android:propertyName="alpha" android:valueFrom="0" android:valueTo="1" android:duration="300"/> |
|
1 2 3 4 5 6 |
val alpha by animateFloatAsState( targetValue = 1f, animationSpec = tween(300) ) Box(modifier = Modifier.alpha(alpha)) { /* ... */ } |
サンプルコードの入手先とセットアップ手順
公開リポジトリ
- GitHub: https://github.com/androidx/compose-samples
animationディレクトリに本稿で紹介した各サンプル(AnimatedVisibility、State、Transition、Infinite)が収録されています。- README に Compose 1.6 用の Gradle 設定例と Layout Inspector の有効化手順が記載。
ローカル環境構築手順
- リポジトリをクローン
bash
git clone https://github.com/androidx/compose-samples.git
cd compose-samples/animation
- Android Studio でプロジェクトを開く
-
File > Open→ 上記フォルダを選択。 -
依存関係の確認(build.gradle.kts)
kotlin
implementation("androidx.compose.ui:ui:1.6.0")
implementation("androidx.compose.animation:animation:1.6.0")
implementation("androidx.activity:activity-compose:1.8.0")
- Sync 後にデバイス/エミュレータで実行
DemoAppの各画面からサンプルを確認でき、同時に Layout Inspector でアニメーションを検証可能。
まとめ
- Compose のアニメーションは Visibility / State / Transition / Infinite の四カテゴリに整理されており、公式ガイドが充実している。
AnimatedVisibilityとanimate*AsStateは最もシンプルで、条件分岐や単一プロパティの変化をすぐにアニメーション化できる。- 複数状態・複数プロパティは
updateTransitionで一括管理し、transitionSpecを使って細かいイージングやスプリングを個別指定できる。 - 無限アニメーションは
rememberInfiniteTransitionとrepeatableの組み合わせで実装し、Compose 1.6 の最適化によりパフォーマンスへの影響は低減。 - デバッグは Layout Inspector の Animation タブが最も直感的で、状態遷移の可視化に有効。
- XML からの移行は「開始タイミング・イージング・繰り返し回数」の三点をチェックすればスムーズに完了できる。
- 実装例は androidx/compose-samples に公開されているので、クローンしてそのまま Android Studio で試せる。
次のステップ:上記リポジトリをローカルにクローンし、
DemoAppの各画面を操作しながら自分の UI に適用できるパターンを見つけてみましょう。
本稿の情報は 2024 年 11 月時点の公式資料に基づいています。Compose のバージョンが上がった際は、リリースノートで API の変更点をご確認ください。