Navigation Composeのアニメーションまとめ 

## はじめに
Navigation Compose を使った際のアニメーションが気になったので、勉強がてらまとめてみました。

## Navigation Compose でのアニメーションについて
以前までは [Accompanist Navigation Animation](https://google.github.io/accompanist/navigation-animation/) というライブラリが利用されていたそうですが、version 2.7.0 以降では Navigation Compose 自体でアニメーションがサポートされるようになったそうです。

>AnimatedContent が安定版になったため、コードを Accompanist Navigation Animation から Navigation Compose 自体に戻せるようになりました。
>[Navigation version 2.7.0](https://developer.android.com/jetpack/androidx/releases/navigation?hl=ja#version_270_3)

Navigation では以下のようにして、 `composable()` の引数を指定することでアニメーションを指定できます。

```kotlin
composable(
    route = "Screen",
    enterTransition = {
        fadeIn(animationSpec = tween(durationMillis = 500), initialAlpha = 0.5f)
    },
    exitTransition = {
        fadeOut(animationSpec = tween(durationMillis = 500), targetAlpha = 0.5f)
    },
) {
    Screen()
}
```
enterTransition などの説明は[こちらの記事](https://zenn.dev/irihi/articles/2fce7f66e49d6c#%E7%94%BB%E9%9D%A2%E9%81%B7%E7%A7%BB%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)でよくまとめらているのでここでは省略します。この記事では Navigation で指定できるアニメーションの種類をまとめます。Navigation で指定できるアニメーションの種類は以下のようになっています。
||EnterTransition|ExitTransition|
|-|-|-|
|フェード|fadeIn|fadeOut|
|スケール|scaleIn|scaleOut|
|スライド|slideIn, slideInHorizontally, slideInVertically|slideOut, slideOutHorizontally, slideOutVertically|
|拡大・縮小|expandIn, expandHorizontally, expandVertically|shrinkOut, shrinkHorizontally, shrinkVertically|

以降では各アニメーションについて述べていきます。

## フェード
### fadeIn(fadeOut)
```kotlin
fun fadeIn(
    animationSpec: FiniteAnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow),
    initialAlpha: Float = 0.0f
): EnterTransition
```
`initialAlpha`で指定した値から1fまで、`animationSpec`で指定されたアニメーションスペックを使用して、遷移先の内容をフェードインさせる。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/166758e8-e165-97c6-4668-20527791de7d.gif" width=300>

## スケール
### scaleIn(scaleOut)
```kotlin
fun scaleIn(
    animationSpec: FiniteAnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow),
    initialScale: Float = 0.0f,
    transformOrigin: TransformOrigin = TransformOrigin.Center
): EnterTransition
```
遷移先を`initialScale`から1fまでスケールさせる。`transformOrigin`は全体のサイズの割合でスケールする中心点を定義する。
`scaleIn`は`+`演算子を使用してほかの`EnterTransition`と組み合わせることができる。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/c7bdbfd1-c48f-5a32-9d46-73b6bfbd8bfa.gif" width=300>

## スライド
### slideIn(slideOut)
```kotlin
fun slideIn(
    animationSpec: FiniteAnimationSpec<IntOffset> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntOffset.VisibilityThreshold
        ),
    initialOffset: (fullSize: IntSize) -> IntOffset
): EnterTransition
```
遷移先を`initialOffset`から`IntOffset(0, 0)`までスライドさせる。正の`x`値は右から左へ、負の`x`値は遷移先を右にスライドさせる。正の`y`値は上方向、負の`y`値は下方向に対応している。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/182c570c-f32f-b4d6-c3b7-4b28ee617f8f.gif" width=300>

### slideInHorizontally(slideOutHorizontally)
```kotlin
fun slideInHorizontally(
    animationSpec: FiniteAnimationSpec<IntOffset> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntOffset.VisibilityThreshold
        ),
    initialOffsetX: (fullWidth: Int) -> Int = { -it / 2 }
): EnterTransition
```
`slideIn`の水平方向限定の遷移。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/beed3b88-110c-30ea-f099-36bbce13169a.gif" width=300>

### slideInVertically(slideOutVertically)
```kotlin
fun slideInVertically(
    animationSpec: FiniteAnimationSpec<IntOffset> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntOffset.VisibilityThreshold
        ),
    initialOffsetY: (fullHeight: Int) -> Int = { -it / 2 }
): EnterTransition
```
`slideIn`の垂直方向限定の遷移。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/708aee9b-51f1-9c8f-1acb-15ac6fc1c805.gif" width=300>

## 拡大・縮小
### expandIn(shrinkOut)
```kotlin
fun expandIn(
    animationSpec: FiniteAnimationSpec<IntSize> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntSize.VisibilityThreshold
        ),
    expandFrom: Alignment = Alignment.BottomEnd,
    clip: Boolean = true,
    initialSize: (fullSize: IntSize) -> IntSize = { IntSize(0, 0) }
): EnterTransition
```
`initialSize`で指定した大きさから、フルサイズまで拡大される。同時に、`expandFrom`は遷移先のどの部分が初めに表示されるかをしていする。
`clip`はアニメーション境界の外側のコンテンツを表示するかを決める。`clip`が`true`の時はアニメーション境界内のコンテンツのみが表示される。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/cd72338d-4b7d-c567-9f56-bef0b69a0d5f.gif" width=300>

### expandHorizontally(shrinkHorizontally)
```kotlin
fun expandHorizontally(
    animationSpec: FiniteAnimationSpec<IntSize> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntSize.VisibilityThreshold
        ),
    expandFrom: Alignment.Horizontal = Alignment.End,
    clip: Boolean = true,
    initialWidth: (fullWidth: Int) -> Int = { 0 }
): EnterTransition
```
#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/57eb44a4-c87f-4fe8-d3e5-7bef16fa07a6.gif" width=300>

### expandVertically(shrinkVertically)
```kotlin
fun expandVertically(
    animationSpec: FiniteAnimationSpec<IntSize> = spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntSize.VisibilityThreshold
        ),
    expandFrom: Alignment.Vertical = Alignment.Bottom,
    clip: Boolean = true,
    initialHeight: (fullHeight: Int) -> Int = { 0 }
): EnterTransition
```
`ExpandIn`の垂直版。

#### 動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1120135/69712e04-330d-9351-0157-4408adaea7ad.gif" width=300>

## 作成したアプリ
https://github.com/HikaruYam/Navigation-Compose-Animation

## 参考
- [ナビゲーション](https://developer.android.com/jetpack/androidx/releases/navigation?hl=ja)
- [Jetpack Composeで画面遷移アニメーションしたいときに役立つであろう情報詰め合わせ](https://zenn.dev/irihi/articles/2fce7f66e49d6c#%E7%94%BB%E9%9D%A2%E9%81%B7%E7%A7%BB%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)
- [EnterTransition](https://developer.android.com/reference/kotlin/androidx/compose/animation/EnterTransition)
- [ExitTransition](https://developer.android.com/reference/kotlin/androidx/compose/animation/ExitTransition)