Android で Twitter のいいね！みたいなアニメーションを実現する


これは [スピカ Advent Calendar 2015](http://qiita.com/advent-calendar/2015/spika) の１２日目(12/12)の投稿です。

今回は [Android版ネイルブック](https://play.google.com/store/apps/details?id=jp.nailbook) でも実装している、Twitter のいいね！みたいなアニメーションを実現する方法について書きます。実際に実機で動きを見てみたい場合は、アプリをダウンロードしてみてください（宣伝）。

![image1.gif](https://qiita-image-store.s3.amazonaws.com/0/35733/2fa89465-a3bc-1199-3603-780990c47305.gif "image1.gif")

ただ難しくはなく、これぐらいのアニメーションであれば古くからある [View Animation](http://developer.android.com/intl/ja/guide/topics/graphics/view-animation.html) で実現できます。

## 1. 適当に画像を用意

例として Google の [Material icon](https://www.google.com/design/icons/) の `favorite(ハート画像)` で説明します。普通に `ImageView` として配置します。

![スクリーンショット 2015-12-11 23.21.26.png](https://qiita-image-store.s3.amazonaws.com/0/35733/8fb80d54-0859-1e48-dee9-3c977c8fd19f.png "スクリーンショット 2015-12-11 23.21.26.png")

> ちなみに `Material icon` を Android Studio で利用する場合は [Android Material Design Icon Generator Plugin](https://github.com/konifar/android-material-design-icon-generator-plugin) を利用すると捗ります。こちらの投稿でも紹介しました。
> ⇒ [私が利用している Android Studio プラグイン 〜2015年版〜](http://qiita.com/hkusu/items/14a69dbdcb83ea0f1c24)

## 2. アニメーション用の XML ファイルを用意する

次のような XML ファイルを用意します。`Interpolator` には `OvershootInterpolator` を採用します。

```xml:res/anim/touch.xml
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/overshoot_interpolator"
    >
<scale
    android:fromXScale="0.5"
    android:toXScale="1"
    android:fromYScale="0.5"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="300"
    android:fillAfter="true"
    />
</set>
```

各属性の意味の説明はここでは省きますが、ポイントは `fromXScale` および `fromYScale` を `0.5` にしている（つまり一旦、50% に縮小したところからアニメーションを開始している）点です。

## 3. アニメーションを実行するコードを書く

例えば『ハート画像をクリックしたらアニメーションを実行する』コードは次のようになります。

```java:MainActivity.java
// ...

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = (ImageView) findViewById(R.id.image_favorite);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.touch);
                view.startAnimation(animation);
            }
        });
    }
}
```

アニメーションを実行している箇所を抜粋すると、たった２行です。

```java:
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.touch);
view.startAnimation(animation);
```

以上で完成です！

![image1.gif](https://qiita-image-store.s3.amazonaws.com/0/35733/2fa89465-a3bc-1199-3603-780990c47305.gif "image1.gif")

この方法でのアニメーションは `View` 類だけでなくレイアウトにも適用することができます。

```java:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_hoge);
relativeLayout.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.touch);
        view.startAnimation(animation);
    }
});
```

実行するとこんな感じです。レイアウトの中身も追従してアニメーションしてくれます。

![image2.gif](https://qiita-image-store.s3.amazonaws.com/0/35733/9b85508a-ee85-3ebb-5e45-b59dba7fe733.gif "image2.gif")

また `Interpolator` を変えれば、また違ったアニメーション（例えば `BounceInterpolator` を適用するとバウンドするような動き）が実現できるので、是非いろいろ試してもらえればと思います。その際 `Interpolator` は上記のように XML ファイルに記載してもよいですし、次のようにコードで指定することもできます。

```java:
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.touch);
animation.setInterpolator(new BounceInterpolator());
view.startAnimation(animation);
```

アニメーションにリスナーをセットして、アニメーション開始/終了時のイベントを拾って何かすることも出来ます。

```java:
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.touch);
animation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        Log.d("animation", "始まったよ");
    }
    @Override
    public void onAnimationEnd(Animation animation) {
        Log.d("animation", "終わったよ");
    }
    @Override
        public void onAnimationRepeat(Animation animation) {
    }
});
view.startAnimation(animation);
```

# おわりに

このように、アニメーションを適用することでインタラクティブで動きのあるアプリが実現できますので是非ためしてもらえればと思います。

それでは良い週末を！