[Android]ゲームでよくある画面をタッチした部分にエフェクトを表示するやつやってみる

タイトルにある通り、画面をタッチするとキラキラしたりマークが出たりするあれをやりたいなぁと思って調べた内容をメモです。

ちなみに、iOS版は[コチラ](http://qiita.com/SAB/items/856adc6cf8cec47cb89b)　※Objective-cです

AndroidはonTouchEventを使うみたいです。

まずはActivityクラスを継承したjavaクラスを作って、onTouchEventを実装します。

```java
public class TapActivity extends Activity {
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tap);
    }

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        float pointX = event.getX();
        float pointY = event.getY();

        return super.onTouchEvent(event);
    }
}
```
これでpointXとpointYにタッチポイントのX座標とY座標が入りますね。
あとはこれを使って上手くやると。

例えば・・・

1.activity_main.xml

```xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android:id="@+id/tapLayout"　←idを付与

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="jp.***.***.***.***.TapActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</RelativeLayout>
```


2.TapActivity.java

```java
public class TapActivity extends Activity {

//ViewGroupを定義
    RelativeLayout tapLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//定義したViewGroupにxmlで付与したidでRelativeLayoutを代入
　　　　　tapLayout = (RelativeLayout)findViewById(R.id.tapLayout)
    }

@Override
    public boolean onTouchEvent(MotionEvent event) {
        float pointX = event.getX();
        float pointY = event.getY();

//画面dpを取得して画像サイズを準備
        float dp = getResources().getDisplayMetrics().density;
        int imgSize = (int)(50 * dp);

//画像を設定
        ImageView img =　new　ImageView(getApplicationContext());
　　　　 img.setImageResource(R.drawable.マーク画像);

//ImageViewに画像サイズを設定
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imgSize, imgSize);
        img.setLayoutParams(params);

//画像の真ん中にタッチポイントが来るように設定
        img.setX(pointX-imgSize/2);
        img.setY(pointY-imgSize/2);
        img.setScaleType(ImageView.ScaleType.FIT_XY);

//画像を半分のサイズに縮小
        img.setScaleX(0.5f);
        img.setScaleY(0.5F);

//画像を描画        
        tapLayout.addView(img);

//0.3秒かけて元のサイズに拡大しながら透明になるアニメーション
        ViewCompat.animate(img)
                 .setDuration(300)
                 .alpha(0)
                 .scaleX(1)
                 .scaleY(1)
                 .setListener(new ViewPropertyAnimatorListener() {
                     @Override
                     public void onAnimationStart(View view) {

                     }

                     @Override
                     public void onAnimationEnd(View view) {
//アニメーション終了時に削除
                         tapLayout.removeView(img);
                     }

                     @Override
                     public void onAnimationCancel(View view) {

                     }
                 }).start();
               

        return super.onTouchEvent(event);
    }
```

でもこれだとタップした時にエフェクトが出てカッコ悪いですね。。。
しかも、画面をタップしながら指を動かしてもついこない。
さらに、アプリ全体を通して画面タップにエフェクト出したい場合、全てのActivityにこんな記述してられないから、こいつを継承したActivityで各画面を実装したい。

こんな欲張りを全て叶えたのが以下です。

1.TapActivity.java

```java
public class TapActivity extends Activity {

//ViewGroupを定義
    ViewGroup viewGroup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

//ViewGroupを受け取るメソッドを準備
    public void setViewGroup(ViewGroup vg){
        viewGroup = vg;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float pointX = event.getX();
        float pointY = event.getY();
        float dp = getResources().getDisplayMetrics().density;
        int imgSize = (int)(50 * dp);

//switch文でアクションを分岐
        switch (event.getAction()){
//画面タップ時
            case MotionEvent.ACTION_DOWN:

                break;

//画面から指が離れた時
            case MotionEvent.ACTION_UP:
                final ImageView img = new ImageView(getApplicationContext());
                img.setImageResource(R.drawable.マーク画像);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imgSize, imgSize);
                img.setLayoutParams(params);

                img.setX(pointX-imgSize/2);
                img.setY(pointY-imgSize/2);
                img.setScaleType(ImageView.ScaleType.FIT_XY);
                img.setScaleX(0.5f);
                img.setScaleY(0.5F);
                viewGroup.addView(img);
                ViewCompat.animate(img)
                        .setDuration(300)
                        .alpha(0)
                        .scaleX(1)
                        .scaleY(1)
                        .setListener(new ViewPropertyAnimatorListener() {
                            @Override
                            public void onAnimationStart(View view) {

                            }

                            @Override
                            public void onAnimationEnd(View view) {
                                viewGroup.removeView(img);
                            }

                            @Override
                            public void onAnimationCancel(View view) {

                            }
                        }).start();
                break;

//画面タップのまま指を動かした時
            case MotionEvent.ACTION_MOVE:
                final ImageView img2 = new ImageView(getApplicationContext());
                img2.setImageResource(R.drawable.マーク画像);
                LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(imgSize, imgSize);
                img2.setLayoutParams(params2);

                img2.setX(pointX-imgSize/2);
                img2.setY(pointY-imgSize/2);
                img2.setScaleType(ImageView.ScaleType.FIT_XY);

                viewGroup.addView(img2);

//0.3秒かけて縮小しながら透明になるアニメーション
                ViewCompat.animate(img2)
                        .setDuration(300)
                        .alpha(0)
                        .scaleX(0.01f)
                        .scaleY(0.01f)
                        .setListener(new ViewPropertyAnimatorListener() {
                            @Override
                            public void onAnimationStart(View view) {

                            }

                            @Override
                            public void onAnimationEnd(View view) {
                                viewGroup.removeView(img2);
                            }

                            @Override
                            public void onAnimationCancel(View view) {

                            }
                        }).start();
                break;
        }


        return super.onTouchEvent(event);
    }
}
```

2.MainActivity.java

```java
//TapActivityを継承
public class MainActivity extends TapActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
   
//xmlファイルで付与したidでViewGroupを渡す  
   　　  setViewGroup((RelativeLayout)findViewById(R.id.mainLayout));
    }

}
```
これでタップしながら動いてもついて来るし、継承させても機能するようになりました。
ちなみに、Androidでは現在表示しているViewGroupを取得する方法がないらしく、継承させてエフェクトを描画させるのに結構苦労しました。
最終的には都度呼び出し側のonCreateで渡してもらうというあまりカッコよくない方法を取ってしまいましたが。。。

何か他に良いやり方をご存知の方がいらっしゃれば是非アドバイスください！