タッチ/フリック + ピンチ のジェスチャーを同時実装する方法 | Androidアプリ開発

※当サイトはアフィリエイト広告を利用しています。

Androidアプリ開発において、タッチ/フリック + ピンチのジェスチャーを同時に実装する方法を紹介します。

なお、タッチ/フリック or ピンチのジェスチャーそのものの実装方法は以下の記事をご覧ください。
スポンサーリンク


タッチ/フリック + ピンチのジェスチャーを同時に実装する方法

タッチ/フリック + ピンチのジェスチャーを同時に実装するにはタッチ/フリック および ピンチ のジェスチャーオブジェクトをそれぞれ取得し、それぞれにタッチイベントを渡してあげるだけです。

以下、サンプルコードです。
public class GestureTestActivity extends AppCompatActivity implements GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener {
    GestureDetectorCompat mGestureDetector;
    ScaleGestureDetector mScaleDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gesture_test);

        mGestureDetector = new GestureDetectorCompat(this, this);
        mScaleDetector = new ScaleGestureDetector(this, this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return event.getPointerCount() > 1 ? mScaleDetector.onTouchEvent(event) : mGestureDetector.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent motionEvent) {
        //タップ時(タップした瞬間)
        Log.d("MY_LOG_TAG", "onDown");
        return true;
    }

    @Override
    public void onShowPress(MotionEvent motionEvent) {
        //タップ時(すこしの間タップした場合)
        Log.d("MY_LOG_TAG", "onShowPress");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {
        //タップしてすぐに離したとき
        Log.d("MY_LOG_TAG", "onSingleTapUp");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
        //スクロール中
        Log.d("MY_LOG_TAG", "onScroll");
        return true;
    }

    @Override
    public void onLongPress(MotionEvent motionEvent) {
        //ロングタップ時
        Log.d("MY_LOG_TAG", "onLongPress");
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) {
        //フリック後
        Log.d("MY_LOG_TAG", "onFling");

        double DiffX = e2.getX() - e1.getX();
        double DiffY = e2.getY() - e1.getY();
        double theta = Math.atan(DiffY / DiffX) / Math.PI * 180.0;

        if(theta > -45 && theta < 45) {
            if(DiffX < 0) {
                //Right flick
            } else {
                //Left flick
            }
        } else {
            if (DiffY < 0) {
                //Up flick
            } else {
                //Down flick
            }
        }

        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        //ピンチ動作中
        Log.d("MY_LOG_TAG", "onScale");
        if(scaleGestureDetector.getScaleFactor() > 1) {
            //拡大動作
            Log.d("MY_LOG_TAG", "拡大");
        } else {
            //縮小動作
            Log.d("MY_LOG_TAG", "縮小");
        }
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
        //ピンチ動作開始
        Log.d("MY_LOG_TAG", "onScaleBegin");
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
        //ピンチ動作終了
        Log.d("MY_LOG_TAG", "onScaleEnd");
    }
}

サンプルコードの解説

まず、タッチ/フリック および ピンチ のジェスチャーオブジェクトをそれぞれ取得します。
    GestureDetectorCompat mGestureDetector;
    ScaleGestureDetector mScaleDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gesture_test);

        mGestureDetector = new GestureDetectorCompat(this, this);
        mScaleDetector = new ScaleGestureDetector(this, this);
    }

あとはそれぞれのゲスチャーオブジェクトにタッチイベントを渡してあげるだけです。
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return event.getPointerCount() > 1 ? mScaleDetector.onTouchEvent(event) : mGestureDetector.onTouchEvent(event);
    }

getPointerCountでタッチの指の数を判定し、ピンチ or タッチ/フリック のジェスチャーオブジェクトにそれぞれタッチイベントを渡してやります。

※StackOverFlowなどには以下のように書かれていることが多いですが、個人的には上記のようにタッチの指の数を判定した方がなんとなく安定している気がします(すみません。体感で、明確な根拠なしです)。
return mScaleDetector.onTouchEvent(event) | mGestureDetector.onTouchEvent(event);

まとめ

Androidアプリ開発において、タッチ/フリック + ピンチのジェスチャーを同時に実装する方法を紹介しました。

なお、タッチ/フリック or ピンチのジェスチャーそのものの実装方法は以下の記事をご覧ください。