onTouch
タッチをキャッチしてダブルタップをキャプチャする方法をACTION_UP
使用していますGestureDetector
。私の問題は、ダブルタップすると、タップしてからダブルタップしてからタップすることです。ダブルタップでタップなどをブロックする方法はありますか? 私はその動作が正しいことを論理的に知っているので、コメントする別の方法を見つけることをアドバイスする場合は、反対票を投じないでください。ありがとう!
3 に答える
britzlが言っていることよりも正確に言うと、GestureDetector
何かがシングルタップ、ダブルタップ、長押しなどであるかどうかを判断する実際の作業を行います。 は、認識したものを示すSimpleGestureListener
ために使用する単なる「リスナー」です。GestureDetector
実装OnGestureListener
しOnDoubleTapListener
て、常に false を返すだけです。のスニペットをチェックしてonTouchEvent(MotionEvent)
くださいGestureDetector
:
case MotionEvent.ACTION_DOWN:
if (mDoubleTapListener != null) {
boolean hadTapMessage = mHandler.hasMessages(TAP);
if (hadTapMessage) mHandler.removeMessages(TAP);
if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
// This is a second tap
mIsDoubleTapping = true;
// Give a callback with the first tap of the double-tap
handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
// Give a callback with down event of the double-tap
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
} else {
// This is a first tap
mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
}
}
mDownFocusX = mLastFocusX = focusX;
mDownFocusY = mLastFocusY = focusY;
if (mCurrentDownEvent != null) {
mCurrentDownEvent.recycle();
}
mCurrentDownEvent = MotionEvent.obtain(ev);
mAlwaysInTapRegion = true;
mAlwaysInBiggerTapRegion = true;
mStillDown = true;
mInLongPress = false;
mDeferConfirmSingleTap = false;
if (mIsLongpressEnabled) {
mHandler.removeMessages(LONG_PRESS);
mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
+ TAP_TIMEOUT + LONGPRESS_TIMEOUT);
}
mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
handled |= mListener.onDown(ev);
break;
次に、適切なリスナーを使用してを作成することにより、目的の結果を取得できます。GestureDetector
final View.OnTouchListener touch_listener = new View.OnTouchListener() {
@Override public boolean onTouch(View view, MotionEvent event) {
return _gesture_detector.onTouchEvent(event);
}
private final GestureDetector _gesture_detector = new GestureDetector(getContext()
, new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapConfirmed(MotionEvent event) {
// TODO: implement single tap behavior
// NOTE: returning true indicates that the gesture was handled
return true;
}
@Override public boolean onDoubleTap(MotionEvent event) {
// TODO: implement double tap behavior
// NOTE: returning true indicates that the gesture was handled
return true;
}
});
};
そしてそこから、これは動作OnTouchListener
が必要な に設定できますView
。
デフォルトGestureHandler
( a Handler
)を使用して機能します:
private class GestureHandler extends Handler {
GestureHandler() {
super();
}
GestureHandler(Handler handler) {
super(handler.getLooper());
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_PRESS:
mListener.onShowPress(mCurrentDownEvent);
break;
case LONG_PRESS:
dispatchLongPress();
break;
case TAP:
// If the user's finger is still down, do not count it as a tap
if (mDoubleTapListener != null) {
if (!mStillDown) {
mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
} else {
mDeferConfirmSingleTap = true;
}
}
break;
default:
throw new RuntimeException("Unknown message " + msg); //never
}
}
}
mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
の行を思い出してくださいGestureDetector
。有効なダブルタップ ジェスチャのタイムアウト期間だけ、タップの通知を遅らせます。if (hadTapMessage) mHandler.removeMessages(TAP);
からの行はGestureDetector
、有効なダブルタップでその通知を削除します。はGestureHandler
遅延後にタップ通知を受信し、コールバックを使用して with に通知GestureListener
しmDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
ます。は、タップ通知の受信時にユーザーの指が下にある場合に、 ( によって処理される)GestureHandler
へのコールバックを遅らせます。MotionEvent.ACTION_UP
GestureDetector
britzl が提案することに加えて、ロジックを少し確認したい場合があります。
ダブルタップで複数になるとは思いません。あなたが言及したように、単に4つのイベントが発生するだけです。Gesture ライブラリは (私が思うに) 最良の選択ですが、次のことを考慮する必要があります。
- Motionevent のタイムスタンプ (メソッドの 1 つ) を ACTION_UP に保存し、次のアクションと比較します。タイムアウトがあれば、タップかダブルタップかがわかります。
それがジェスチャーリスナーが行うことです