2

我正在使用该onTouch方法来捕捉触摸ACTION_UPGestureDetector捕捉双击,我的问题是双击导致点击然后双击,然后点击。有没有办法让双击阻止水龙头或类似的东西?我从逻辑上知道它的做法是正确的,所以如果你建议我找到另一种方式只是评论,请不要投反对票。谢谢!

4

3 回答 3

7

我建议您切换到SimpleGestureListener并使用onDoubleTap()onSingleTapConfirmed()方法。

于 2013-05-21T21:41:42.323 回答
3

为了比britzl所说的更准确,GestureDetector确定某物何时是单击、双击、长按等的实际工作。这SimpleGestureListener只是一个“侦听器”,GestureDetector用于指示它识别的内容。它实现OnGestureListener并且OnDoubleTapListener总是返回false。查看来自onTouchEvent(MotionEvent)in的片段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回调通知GestureListenerwith mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);。如果在收到点击通知时用户的手指向下,GestureHandler则将延迟回调到MotionEvent.ACTION_UP(由 处理)。GestureDetector

于 2014-01-30T18:45:35.097 回答
0

除了 britzl 建议的内容之外,您可能还想在那里检查一下您的逻辑。

我不认为双击会导致多个事件,它只会导致 4 个事件,就像您提到的那样。虽然手势库是(我认为)最好的选择,但您应该考虑:

  • 将 Motionevent 的时间戳(这是它的方法之一)存储在 ACTION_UP 上,然后将其与下一个动作进行比较。提供超时,您将知道何时是点击或双击。

这就是手势监听器所做的

于 2013-05-21T21:50:13.797 回答