【Jetpack Compose/Android】Navigation Composeでアニメーションを実装する方法!
この記事からわかること
- Kotlin/Android Jetpack ComposeのNavigation Composeの使い方
- 画面遷移でアニメーションを実装方法
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Narwhal Feature Drop
- Kotlin:2.1.10
- Material3
- AGP:8.9.2
- Gradle:8.11.1
- Mac M1:Sequoia 15.6.1
Navigation Composeのアニメーション
「Navigation Compose」では画面遷移時のアニメーションもある程度柔軟に設定できるようになっています。少し前まではJetpack Navigation Compose Animationという別ライブラリに切り出されていたようですが、Ver2.7.0以降から実装が安定しNavigation Composeに再度組み込まれたようです。
Navigation Compose自体の導入や使い方などは以下の記事を参考にしてください。
アニメーションの実装方法
Navigation Composeでのアニメーションはcomposableメソッドの引数で行います。以前はAnimatedNavHostに置き換える必要がありましたがNavHostのままで問題ありません。
composable(
route = Screen.Detail.route(),
arguments = listOf(navArgument(Screen.Detail.ARG_ITEM_ID) { type = NavType.IntType }),
// アニメーション
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 500), initialAlpha = 0.5f)
},
// アニメーション
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 500), targetAlpha = 0.5f)
},
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt(Screen.Detail.ARG_ITEM_ID) ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
導入できるアニメーションタイミングは画面をpush / popした時です。
指定できるアニメーションタイミング
| 引数名 | 概要 |
|---|---|
| enterTransition | 画面遷移して新規画面が表示されるときのアニメーション |
| exitTransition | 現在の画面から別の画面へ遷移するときのアニメーション |
| popEnterTransition | 戻る操作(popBackStack)で画面が再表示されるときのアニメーション |
| popExitTransition | 戻る操作で現在の画面が消えるときのアニメーション |
アニメーションの種類
アニメーションの種類は以下の4つが用意されています。
- フェード・・・fadeIn / fadeOut
- スライド・・・slideIn / slideOut・slideInHorizontally / slideOutHorizontally・ slideInVertically / slideOutVertically
- 拡大・縮小(スケール)・・・scaleIn / scaleOut
フェード
composable(
route = Screen.Detail.route(),
arguments = listOf(navArgument(Screen.Detail.ARG_ITEM_ID) { type = NavType.IntType }),
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 500), initialAlpha = 0.5f)
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 500), targetAlpha = 0.5f)
},
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt(Screen.Detail.ARG_ITEM_ID) ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
スライド
composable(
route = Screen.Detail.route(),
arguments = listOf(navArgument(Screen.Detail.ARG_ITEM_ID) { type = NavType.IntType }),
enterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
},
exitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth / 2 },
animationSpec = tween(500)
)
},
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt(Screen.Detail.ARG_ITEM_ID) ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
スライドイン / アウトさせる方向はinitialOffsetY/targetOffsetXで背御することが可能です。
slideInVertically(
// 画面の下からスライドイン
initialOffsetY = { fullHeight -> fullHeight },
// 画面の上からスライドイン
// initialOffsetY = { fullHeight -> -fullHeight }
)
slideOutVertically(
// 画面の下に向かってスライドアウト
targetOffsetY = { fullHeight -> fullHeight },
// 画面の下に向かってスライドアウト
targetOffsetY = { fullHeight -> -fullHeight },
)
拡大・縮小(スケール)
composable(
route = Screen.Detail.route(),
arguments = listOf(navArgument(Screen.Detail.ARG_ITEM_ID) { type = NavType.IntType }),
enterTransition = {
scaleIn(
animationSpec = tween(500),
initialScale = 0.8f // 最初は80%のサイズから
) + fadeIn(animationSpec = tween(500))
},
exitTransition = {
scaleOut(
animationSpec = tween(500),
targetScale = 0.8f // 80%に縮小しながら消える
) + fadeOut(animationSpec = tween(500))
}
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt(Screen.Detail.ARG_ITEM_ID) ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
FiniteAnimationSpec
各アニメーションAPIにはアニメーションの進み方を制御するために引数animationSpecにFiniteAnimationSpec型で設定を渡すことが可能になっています。ここからアニメーション時間やイージングなどを制御することが可能になっています。
FiniteAnimationSpec
| クラス名 | 概要 |
|---|---|
| tween | 指定した時間でイージングしながら値を変化させる |
| spring | バネの動きをシミュレート |
| keyframes | 特定の時刻ごとに値を設定してアニメーション |
| snap | すぐに値を切り替える |
以下のような形で指定した時間でイージングを設定することが可能です。
fadeIn(
animationSpec = tween(
durationMillis = 500,
easing = LinearOutSlowInEasing
),
initialAlpha = 0.5f
)
アニメーションは重ねられる
先に少し紹介しましたがアニメーションは+で重ねることが可能です。
scaleIn(
animationSpec = tween(500),
initialScale = 0.8f // 最初は80%のサイズから
) + fadeIn(animationSpec = tween(500))
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。







