Spring Animationの動きを理解して使いこなす

>この記事は[VASILY DEVELOPERS BLOG](http://tech.vasily.jp/)にも同じ内容で投稿しています。よろしければ他の記事もご覧ください。

# Spring Animationとは

Spring AnimationはGoogleが公式にサポートしているアニメーションのライブラリで、名前の通りばねの動きを模しています。今年のGoogle I/Oで紹介されました。

[Android Animations Spring to Life (Google I/O '17)](https://www.youtube.com/watch?v=BNcODK-Ju0g)

Spring Animationを使うとわずか数行のコードで美しいバウンドのアニメーションを実装できます。しかし、実際の物理現象を模しているため調整にはちょっとコツが要ります。

# とりあえず使ってみる

Spring Animationを使うにはサポートライブラリが必要なので、build.gradleに一行追記しましょう。

```build.gradle
dependencies {
    .
    .
    .
    implementation "com.android.support:support-dynamic-animation:27.0.0"
}

```

これによりAPI 16以上でSpring Animationが使えるようになります。Spring Animationを読み込めるようになったら、早速簡単なアニメーションを実装してみましょう。ここでは四角形がバウンドするようなアニメーションを作ってみたいと思います。まず、レイアウトに四角形のビューを追加してみましょう。

```xml

<View
    android:id="@+id/square"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_gravity="center|top"
    android:layout_marginTop="20dp"
    android:background="#f00" />

```
次に、以下のコードをアクティビティの任意の場所に追加します。

```kotlin
val square: View = findViewById(R.id.square)
val animation = SpringAnimation(square, DynamicAnimation.TRANSLATION_Y, 500f)
animation.spring.apply {
    dampingRatio = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
    stiffness = SpringForce.STIFFNESS_VERY_LOW
}
animation.start()
```
あとはビルドするだけです。上手く行けば次のようなアニメーションが表示されるはずです。

![20171027110937.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/11d41ab5-1514-70b4-8100-fa0368365b0d.gif)


以上でSpring Animationの導入は終わりです。ここでstiffnessとdamping ratioという2つのパラメータが出てきました。実際にアニメーションの動きを調整する場合にはこれらのパラメータを変えていくことになります。どちらもあまり聞き慣れない言葉だと思いますが、ばねの運動を司る重要な物理パラメータです。次節ではばねの運動について触れていきます。

# ばねの運動について

ばねは引っ張って手を離すと振動を始め、だんだん減衰していきます。このように、ばねの運動は振動と減衰という2つの要素を持ちます。先程触れたstiffnessとdamping ratioはこれらに対応する物理パラメータです。

## stiffness（ばね定数）
stiffnessという単語は日本語に訳すと剛性です。いわゆる高校物理で出てくるばね定数に当たります。stiffnessはばねの固さを表しており、stiffnessが大きいほどばねが固くなって振動が細かくなります。振動の細かさを表す固有振動数とstiffnessには以下の関係があります。

```math
\omega=\sqrt{\frac{k}{m}} \\
\\
\begin{align}
\omega &: \mbox{固有振動数}\\
k &: \mbox{stiffness}\\
m &: \mbox{質量}\\
\end{align}
```

上の関係から、振動の細かさを2倍にしたい場合はstiffnessを2 x 2 = 4倍、3倍にしたい場合はstiffnessを3 x 3 = 9倍…とすれば良いことがわかります。

## damping ratio（減衰比）
damping ratioはばねの減衰の大きさを表しており、大きいほど減衰が早くなります。これにより振動の持続時間を調整できます。ばねの振動はdamping ratioの値により3つのモードに分類できます。

* $\mbox{damping ratio} = 0$ : 単振動
減衰せずに一定の振幅でずっと振動が続くモードです。高校で物理を選択していた方なら一度習ったことがあるはずです。

* $0 < \mbox{damping ratio} < 1$ : 減衰振動
名前の通り減衰しながら振動するモードです。

* $1 \leq \mbox{damping ratio}$ : 臨界減衰or過減衰
振動せずに減衰していくモードです。$\mbox{damping ratio = 1}$の臨界減衰が最も早く減衰します。

これらをグラフに書いたのが下の図です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75424/f94a29cb-82fd-5337-ee44-a9123d09c81d.png)

どのモードを使うかはお好みですが、実際の開発では減衰振動を使うケースが多いと思います。

# Spring Animationの動きを変えてみる

ここまででばねの運動を簡単に説明しました。ここから実際にSpring Animationの動きを調整していきましょう。

## 適用するプロパティ・初期値・最終値を設定する

まずはSpringAnimationのプロパティ・初期値・最終値を設定してみましょう。

```kotlin
val animation = SpringAnimation(
        square, // 適用するビュー
        DynamicAnimation.TRANSLATION_Y, // 適用するプロパティ
        500f // 最終値
)
animation.setStartValue(200f) /*初期値(ここで指定しなかった場合はビューに設定された値が初期値になります)*/
```

アニメーションを適用するプロパティはDynamicAnimationの定数で指定できます。

| ビューのプロパティ | DynamicAnimationの定数 |
|:-:|:-:|
|alpha|DynamicAnimation.ALPHA|
|rotation|DynamicAnimation.ROTATION|
|rotationX|DynamicAnimation.ROTATION_X|
|rotationY|DynamicAnimation.ROTATION_Y|
|scaleX|DynamicAnimation.SCALE_X|
|scaleY|DynamicAnimation.SCALE_Y|
|scrollX|DynamicAnimation.SCROLL_X|
|scrollY|DynamicAnimation.SCROLL_Y|
|translationX|DynamicAnimation.TRANSLATION_X|
|translationY|DynamicAnimation.TRANSLATION_Y|
|translationZ|DynamicAnimation.TRANSLATION_Z|
|x|DynamicAnimation.X|
|y|DynamicAnimation.Y|
|z|DynamicAnimation.Z|

SpringAnimationは1つのインスタンスで1つのプロパティしか設定できません。複数のプロパティにアニメーションを適用する場合には、それぞれにSpringAnimationのインスタンスを用意する必要があります。
適用するパラメータを指定したら初期値と最終値を指定しましょう。Spring Animationは初期値から開始し、最終値を中心に振動してから収束します。拡大するようなアニメーションの場合には最終値を超える瞬間があるので、レイアウトを組む際に注意が必要です。

## 物理パラメータを変えてみる

物理パラメータは定数が幾つか用意されていますが、ここでは前節を踏まえてオリジナルの値を設定してみましょう。stiffnessは100ぐらいを基準に調節していくのがおすすめです。

<div style="margin-bottom: 0;">s: stiffness, dr: damping ratio</div>

| s = 100.0<br>dr = 0.2 | s = 25.0<br>dr = 0.2 | s = 100.0<br>dr = 0.0 | s = 100.0<br>dr = 0.5 | s = 100.0<br>dr = 1.0 |
|:-:|:-:|:-:|:-:|:-:|
| ![20171026160232.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/0fbf9755-9338-cddc-f0ec-415f000c2c87.gif) | ![20171026160352.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/98a5ac27-bc24-0bbe-b215-51bf0c478d56.gif) | ![20171026160403.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/4ea9d329-dcdb-6685-b60c-8256ec8a26e3.gif) | ![20171026160439.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/5860dbf3-2ac5-8976-1640-a2751760dcc2.gif) | ![20171026160449.gif](https://qiita-image-store.s3.amazonaws.com/0/75424/902c64e0-5837-68d8-7c12-407d3e6cafca.gif) |





# まとめ

物理パラメータで調整するのは一見すると難しく思えますが、意味を知れば大分扱いやすくなると思います。Spring Animationは数行のコードで美しいアニメーションを実現できるので、皆様もバウンドのアニメーションを実装する際にぜひ使ってみて下さい。