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

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

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

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

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

ActivityのonCreate処理で

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

```
onTouchの処理内で

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

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

SimpleOnScaleGestureListenerの詳細は以下です。

```
/**
 * ピンチイン/アウトのListener
 */
private SimpleOnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
	// イベントの開始（２点タッチされたタイミングで発生）
	@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;
	}

};
```

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

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

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

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


実装例は以下です。

```
/**
 * ピンチイン/アウトのListener
 */
private SimpleOnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
	// イベントの開始（２点タッチされたタイミングで発生）
	@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で判定処理を行っておきます**

以上