【Android】Physics-based Animations (Google I/O '17)

Google I/O 2017 の Android Animations Spring to Life で発表された Physics-based Animations (物理ベースアニメーション) についてのまとめです。（LT用資料も兼ねてます）

---

## Physics-based Animations

### Physics-based Animationsとは
物理法則に基づいたアニメーションのこと。
（例）Spring Animation
![low_stiffness.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/43a38944-7e26-11c7-aa89-994755fc0200.gif)

---

### 利点
- 自然な見た目
    - 物理ベースで理解しやすく全体的に滑らかになる
- コース修正
    - アニメーションのターゲットが変更されたときに勢いを維持しつつ滑らかに停止できる
- 視覚的違和感の軽減
    - リアルタイムに滑らかに動作することで全体的な違和感を軽減できる

---

### 非物理ベースアニメーションと物理ベースアニメーションの違い

|非物理ベース|物理ベース|
|:-:|:-:|
|![targetchange_oa.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/366f78fd-f1e6-4c0a-2957-b81081570356.gif)|![targetchange_pba.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/27ff0782-d899-16bd-2719-74ac9a491cb0.gif)|
|[ObjectAnimator](https://developer.android.com/reference/android/animation/ObjectAnimator.html)を使ったアニメーション|physics-based APIを使ったアニメーション|

非物理ベースアニメーション（ [Animator](https://developer.android.com/reference/android/animation/Animator.html) を利用したアニメーション）は、ターゲットが変更されたらアニメーションを停止しターゲット変更時点の位置を開始点として新しいターゲットに対してアニメーションを開始する。
物理ベースアニメーションは、ターゲットを変更すると新しい方向へ動こうとする加速度は元々の速度に影響されて新しいターゲットに連続的に移動する。

---

**非物理ベース**アニメーションの速度グラフ
<img width="920" alt="oa_chart.png" src="https://qiita-image-store.s3.amazonaws.com/0/123122/2fa5222e-3b23-0ba7-e381-d9bdddf840ea.png">

---

**物理ベース**アニメーションの速度グラフ
<img width="931" alt="pba_chart.png" src="https://qiita-image-store.s3.amazonaws.com/0/123122/b151a8e0-7651-2b92-fb12-58e30d8f21ca.png">

---

### 使い方
`build.gradle`に以下を追記。（I/O発表時はbeta1でしたが、2017/06/18時点ではbeta2）

```
dependencies {
    compile "com.android.support:support-dynamic-animation:26.0.0-beta2"
}
```
API level 16 (Jelly Bean 4.1.x系)までサポートしている。

---

### 関連クラス

|クラス|説明|
|---|---|
|[android.support.animation](https://developer.android.com/reference/android/support/animation/package-summary.html)|Viewをアニメーションするための主要なAPI。物理ベースのアニメーションを作成・管理するためのクラスが含まれる。|
|[DynamicAnimation](https://developer.android.com/reference/android/support/animation/DynamicAnimation.html)|物理ベースのアニメーションパッケージのベースクラス。すべてのアニメーションのアニメーションライフサイクルと共通の設定を管理。|
|[SpringAnimationhttps](https://developer.android.com/reference/android/support/animation/SpringAnimation.html)|DynamicAnimationクラスのサブクラス。スプリングアニメーションを作成。|
|[SpringForce](https://developer.android.com/reference/android/support/animation/SpringForce.html)|アニメーションで使用される減衰比や剛性などのスプリングのプロパティを定義するクラス。|
|[FlingAnimation](https://developer.android.com/reference/android/support/animation/FlingAnimation.html)|DynamicAnimationクラスのサブクラス。最初の運動量を持ち徐々に減速するフライングアニメーションを作成。|

---

## Spring Animation

### Spring Animationとは
各フレームに適用されるバネの力に基づいて値と速度が計算されるアニメーション。
バネの力は減衰と剛性の特性がある。

（例）手を離したときのスプリングアニメーション
![spring-release.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/338c29c8-70d7-f265-3772-a8db353087c3.gif)

---

### 基本的な使い方
`SpringAnimation`オブジェクト作成して`start()`実行。

```java
final View img = findViewById(R.id.imageView);

// Setting up a spring animation to animate the view’s translationY property with the final spring position at 0.
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);

// Starting the animation
anim.start();
```

---

### 減衰率設定（バウンス設定）

```java
//Setting the damping ratio to create a low bouncing effect.
anim.getSpring().setDampingRatio(DAMPING_RATIO_LOW_BOUNCY);
```

|High bounce|Medium bounce|Low bounce|No bounce|
|:-:|:-:|:-:|:-:|
|![high_bounce.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/73051e09-cb41-6a17-20a4-ae13090b2d96.gif)|![medium_bounce.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/e83e9c73-c280-66e0-15e0-ec827988bd10.gif)|![low_bounce.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/6a9e5736-d26f-1fb9-3346-d68f5e31281c.gif)|![no_bounce.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/2e80adaf-ddaf-f06a-f213-57dbc6b02b62.gif)|

---

### 剛性設定

```java
//Setting the spring with a low stiffness.
anim.getSpring().setStiffness(STIFFNESS_LOW);
```

|High stiffness|Medium stiffness|Low stiffness|Very low stiffness|
|:-:|:-:|:-:|:-:|
|![high_stiffness.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/d18a92d7-3972-f587-5f28-f36f52da8a1e.gif)|![medium_stiffness.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/b99879f6-03d5-7664-f88c-8a270e3bf308.gif)|![low_stiffness (1).gif](https://qiita-image-store.s3.amazonaws.com/0/123122/81042918-431c-75b5-e238-cc888139f18c.gif)|![very_low_stiffness.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/5c5e8c3f-4afa-6288-4663-860decf77ad5.gif)|

---

### Chained Spring Animation
SpringAnimationを組み合わせて使うことで複数のViewを鎖のようにアニメーションさせることもできる。

![spring_chain.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/77e0f210-c589-9f1d-5359-95f7f5cb3404.gif)

---

## Fling Animation
オブジェクトの速度に比例する摩擦力を使ったアニメーション。

![fling-animation.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/e8e5ffe1-8f47-61a4-a116-b6ca9915ac51.gif)

```java
FlingAnimation fling = new FlingAnimation(view, DynamicAnimation.SCROLL_X);
```

---

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

Animator | Android Developers
https://developer.android.com/reference/android/animation/Animator.html

ObjectAnimator | Android Developers
https://developer.android.com/reference/android/animation/ObjectAnimator.html

android.support.animation | Android Developers
https://developer.android.com/reference/android/support/animation/package-summary.html

DynamicAnimation | Android Developers
https://developer.android.com/reference/android/support/animation/DynamicAnimation.html

SpringAnimation | Android Developers
https://developer.android.com/reference/android/support/animation/SpringAnimation.html

SpringForce | Android Developers
https://developer.android.com/reference/android/support/animation/SpringForce.html

FlingAnimation | Android Developers
https://developer.android.com/reference/android/support/animation/FlingAnimation.html

Physics-based Animations | Android Developers
https://developer.android.com/topic/libraries/support-library/preview/physics-based-animation.html