LoginSignup
14
17

More than 5 years have passed since last update.

Android ピンチイン ピンチアウト ロングプレス 併用する

Last updated at Posted at 2015-12-10

ピンチイン ピンチアウト ロングプレス 併用する方法

スマホのアプリで、画像をピンチイン・アウトすると拡大・縮小して
長押しするとコンテキストメニューとか表示させたい時ってありますよね?

例えばカメラアプリを開発している時とかにピンチイン・アウトで拡大・縮小して
ロングプレスで写真撮影するとか。。。

ピンチイン ピンチアウトのジェスチャーはScaleGestureDetectorを使用して行います。

ActivityのonCreate処理で

// ScaleGestureDetectorを生成
ScaleGestureDetector scaleGesture = new ScaleGestureDetector(this, scaleGestureListener);

onTouchの処理内で

// イベントを発生
scaleGesture.onTouchEvent(event);

とすると、ピンチイン ピンチアウトのイベントを拾うことができます。

SimpleOnScaleGestureListenerの詳細は以下です。

/**
 * ピンチイン/アウトのListener
 */
private SimpleOnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
    // イベントの開始(2点タッチされたタイミングで発生)
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector)
    {
        return super.onScaleBegin(detector);
    }
    // イベントの開始(指を離すと発生)
    @Override
    public void onScaleEnd(ScaleGestureDetector detector)
    {
        super.onScaleEnd(detector);

    }

    // ピンチイン/アウト
    @Override
    public boolean onScale(ScaleGestureDetector detector)
    {

    };
}

ロングプレスの処理も同様に
ActivityのonCreate処理で

// GestureDetectorを生成
GestureDetector gesture = new GestureDetector(this, gestureListener);

onTouchの処理内で

// イベントを発生
gesture.onTouchEvent(event);
```

とします。

SimpleOnScaleGestureListenerの詳細は以下です。

private OnGestureListener gestureListener = new GestureDetector.OnGestureListener()
{
    // 押下イベント
    @Override
    public boolean onDown(MotionEvent e)
    {
        return true;
    }
    // 単純押下時のみ発生
    @Override
    public void onShowPress(MotionEvent e)
    {
    }
    // シングルタッチアップイベント
    @Override
    public boolean onSingleTapUp(MotionEvent e)
    {
    }

    // スクロール処理イベント 
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
    }

    /** 長押し処理イベント */
    @Override
    public void onLongPress(MotionEvent e)
    {
    }

    // フリック処理イベント
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        return false;
    }

};

ただ2つの処理と単純に記載した場合、
ピンチイン ピンチアウト中にロングプレスイベントが発生してしまいます。

理由は
onTouchのイベントが
1. 1点タッチダウン
2. 2点タッチダウン
3. 2点ムーブ
4. 2点タッチアップ
5. 1点タッチアップ

といったように同時に2本の指をタッチしても、1点タッチダウンが先に発生してしまうため、
ピンチイン中にロングプレスイベントが発生します。

解決策としてはピンチイン ピンチアウト中はロングプレスのイベントをキャンセルさせるように
します。

実装例は以下です。

/**
 * ピンチイン/アウトのListener
 */
private SimpleOnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
    // イベントの開始(2点タッチされたタイミングで発生)
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector)
    {
        // ロングプレスイベントを発生させないようにする
        gesture.setIsLongpressEnabled(false);
        return super.onScaleBegin(detector);
    }
    // イベントの開始(指を離すと発生)
    @Override
    public void onScaleEnd(ScaleGestureDetector detector)
    {
        // ロングプレスイベントを発生させるようにする。
        gesture.setIsLongpressEnabled(true);
        super.onScaleEnd(detector);

    }

    // ピンチイン/アウト
    @Override
    public boolean onScale(ScaleGestureDetector detector)
    {

    };
}

GestureDetector#setIsLongpressEnabledが重要です。
これを行うことにより、イベントをキャンセルさせることができます。

またタイミングによってロングプレスイベントが発生する可能性もあるので、

    /** 長押し処理イベント */
    @Override
    public void onLongPress(MotionEvent e)
    {

        if (gesture.isLongpressEnabled()) 
        {
            autoFocus(true);
        }
    }

onLongPress内にGestureDetector#isLongpressEnabledで判定処理を行っておきます

以上

14
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17