ピンチイン ピンチアウト ロングプレス 併用する方法
スマホのアプリで、画像をピンチイン・アウトすると拡大・縮小して
長押しするとコンテキストメニューとか表示させたい時ってありますよね?
例えばカメラアプリを開発している時とかにピンチイン・アウトで拡大・縮小して
ロングプレスで写真撮影するとか。。。
ピンチイン ピンチアウトのジェスチャーは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で判定処理を行っておきます**
以上