FloatingActionButtonのアニメーションを作っているMotionSpecって何？

[Ateam Lifestyle Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-lifestyle)の3日目は
株式会社エイチームライフスタイル 名古屋開発部 の@chardenが担当します！

ライフスタイルで数少ないアプリエンジニアなので今回もアプリの記事で行かせていただきます！

自社アプリでFloatingActionButtonを追加したときにアニメーションを制御したくて調べた内容を記事にします。

## MotionSpecとは

https://github.com/material-components/material-components-android

material-components-androidに含まれるViewのアニメーションを決めるもの

FloatingActionButtonにおいてデフォルトでは、表示アニメーションとして以下のようなXMLが設定されています。

```xml:design_fab_show_motion_spec.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright 2017 The Android Open Source Project

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<set xmlns:android="http://schemas.android.com/apk/res/android">
  <objectAnimator
      android:propertyName="opacity"
      android:startOffset="0"
      android:duration="200"
      android:interpolator="@interpolator/mtrl_linear_out_slow_in"/>
  <objectAnimator
      android:propertyName="scale"
      android:startOffset="0"
      android:duration="200"
      android:interpolator="@interpolator/mtrl_linear_out_slow_in"/>
  <objectAnimator
      android:propertyName="iconScale"
      android:startOffset="0"
      android:duration="0"
      android:interpolator="@interpolator/mtrl_fast_out_slow_in"/>
</set>
```

非表示になる場合は、design_fab_hide_motion_spec.xmlが使われています。

デフォルトでは下記のようなアニメーションで動作します。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/33394e66-df8d-01c5-1056-887783362b34.gif' width='300px'>

## MotionSpecに対応したMaterialDesignComponent(2019年12月時点)

* FloatingActionButton
* Chip

## 設定できる項目

### FloatingActionButtonの場合
#### Property
* opacity 
    * 不透明度
* scale
    * Viewの拡大縮小
* iconScale
    * アイコンの拡大縮小
    
#### それぞれの設定

* startOffset
    * 始点の位置
* duration
    * 持続時間
* interpolator
    * 動作補間

## interpolator(動作補間)とは

以下の動画を見てみるのがわかりやすい

https://www.youtube.com/watch?v=6UL7PXdJ6-E

だんだん早く、だんだん遅くなどアニメーションの動作の仕方を変更することができる

## 実際に設定値を変えてみると

| 通常(duration = 200ms)| duration = 1s | bounce|
|:-----------:|:------------:|:------------:|
| ![normal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/9f80b05d-c671-f880-bb10-3c1cc9a720b3.gif)| ![duration.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/2250214e-feb1-44c3-3a3c-5ce4141b44a4.gif)| ![bounce.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/bb4de30f-fbbd-d671-a6cc-e102f5509350.gif)|


## 独自でinterpolatorを作成できる

動作補間を``sin4x``としてCustomInterpolator.javaを作成しました。

実際の動作はこんな形

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/cd3649ec-dcec-3f5c-c89b-c55dd440a751.gif" width="300px">

波形で表すとこんな感じ

![geogebra-export (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7668/d66a3759-0132-854c-981a-42068b48a588.png)

実際のコード

```kotlin:CustomInterpolator.kotlin
import android.view.animation.Interpolator
import kotlin.math.sin

class CustomInterpolator : Interpolator {
    override fun getInterpolation(v: Float): Float {
        return sin(4 * v)
    }
}
```

XMLではうまく指定できないようなのでコードから指定

```kotlin
val motionSpec = MotionSpec.createFromResource(this, R.animator.show)
motionSpec?.setTiming("scale", MotionTiming(0, 1000, CustomInterpolator()))
fab.showMotionSpec = motionSpec
```

## まとめ
material-components-androidでは一部のComponentにてMotionSpecにてアニメーションを設定することができます。
今後は、アニメーションをうまく使うことにより、より心地よいユーザー体験をできるようにしていきたいと思っています！

[Ateam Lifestyle Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-lifestyle)の4日目は、@dayamaguchi1がお送りします！！インフラエンジニアがどんな記事を書いてくれるか楽しみですね！

"挑戦"を大事にするエイチームグループでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。興味を持たれた方はぜひエイチームグループ採用サイトを御覧ください。
https://www.a-tm.co.jp/recruit/