Android手势 怎么样才算长按(GestureDetector源码)
来源:互联网 发布:淘宝衣服兼职模特招聘 编辑:程序博客网 时间:2024/06/10 20:51
GestureDetector里onLongPress方法的回调来自
private void dispatchLongPress() { mHandler.removeMessages(TAP); mDeferConfirmSingleTap = false; mInLongPress = true; mListener.onLongPress(mCurrentDownEvent); //这里 }一看dispatch方法——HOHO 是的, 你没猜错 就是handler里分发的
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: //就是这个message控制了啦 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 } }
Come on! 进入正题OnTouchEvent的手势处理
这个LONG_PRESS的message发送的地方有且只有一个
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); //喏喏 就是这里是一个delayMessage } mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); handled |= mListener.onDown(ev); break;找到啦delay的时长总共是(TAP_TIMEOUT_LONGPRESS_TIMEOUT)
它们分别是多少呢?
private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); //缺省500毫秒 Settings.Secure可设置 private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); //100毫秒
也就是说缺省总共0.6秒。
主题是解决了,那为什么要发一个延迟message哪?
因为如果不符合长按条件 咱可以取消啊
场景1: MOVE的时候
case MotionEvent.ACTION_MOVE: if (mInLongPress || mInContextClick) { break; } final float scrollX = mLastFocusX - focusX; final float scrollY = mLastFocusY - focusY; if (mIsDoubleTapping) { // Give the move events of the double-tap handled |= mDoubleTapListener.onDoubleTapEvent(ev); } else if (mAlwaysInTapRegion) { //这个前提条件看字面意思是所有区域都视为tap区域? final int deltaX = (int) (focusX - mDownFocusX); final int deltaY = (int) (focusY - mDownFocusY); int distance = (deltaX * deltaX) + (deltaY * deltaY); if (distance > mTouchSlopSquare) { //如果还没longPress就超出TouchSlop了 handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); mLastFocusX = focusX; mLastFocusY = focusY; mAlwaysInTapRegion = false; mHandler.removeMessages(TAP); mHandler.removeMessages(SHOW_PRESS); mHandler.removeMessages(LONG_PRESS);//那你就没机会longPress了? 待验证前提条件 } if (distance > mDoubleTapTouchSlopSquare) { mAlwaysInBiggerTapRegion = false; } } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); mLastFocusX = focusX; mLastFocusY = focusY; } break;场景2: UP的时候
case MotionEvent.ACTION_UP: mStillDown = false; MotionEvent currentUpEvent = MotionEvent.obtain(ev); if (mIsDoubleTapping) { // Finally, give the up event of the double-tap handled |= mDoubleTapListener.onDoubleTapEvent(ev); } else if (mInLongPress) { mHandler.removeMessages(TAP); mInLongPress = false; } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) { handled = mListener.onSingleTapUp(ev); if (mDeferConfirmSingleTap && mDoubleTapListener != null) { mDoubleTapListener.onSingleTapConfirmed(ev); } } else if (!mIgnoreNextUpEvent) { // A fling must travel the minimum tap distance final VelocityTracker velocityTracker = mVelocityTracker; final int pointerId = ev.getPointerId(0); velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); final float velocityY = velocityTracker.getYVelocity(pointerId); final float velocityX = velocityTracker.getXVelocity(pointerId); if ((Math.abs(velocityY) > mMinimumFlingVelocity) || (Math.abs(velocityX) > mMinimumFlingVelocity)){ handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY); } } if (mPreviousUpEvent != null) { mPreviousUpEvent.recycle(); } // Hold the event we obtained above - listeners may have changed the original. mPreviousUpEvent = currentUpEvent; if (mVelocityTracker != null) { // This may have been cleared when we called out to the // application above. mVelocityTracker.recycle(); mVelocityTracker = null; } mIsDoubleTapping = false; mDeferConfirmSingleTap = false; mIgnoreNextUpEvent = false; mHandler.removeMessages(SHOW_PRESS); mHandler.removeMessages(LONG_PRESS); //这是必然的 break;场景3 按钮点击的时候?
/** * Analyzes the given generic motion event and if applicable triggers the * appropriate callbacks on the {@link OnGestureListener} supplied. * * @param ev The current motion event. * @return true if the {@link OnGestureListener} consumed the event, * else false. */ public boolean onGenericMotionEvent(MotionEvent ev) { if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onGenericMotionEvent(ev, 0); } final int actionButton = ev.getActionButton(); switch (ev.getActionMasked()) { case MotionEvent.ACTION_BUTTON_PRESS: if (mContextClickListener != null && !mInContextClick && !mInLongPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY || actionButton == MotionEvent.BUTTON_SECONDARY)) { if (mContextClickListener.onContextClick(ev)) { mInContextClick = true; mHandler.removeMessages(LONG_PRESS); mHandler.removeMessages(TAP); return true; } } break; case MotionEvent.ACTION_BUTTON_RELEASE: if (mInContextClick && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY || actionButton == MotionEvent.BUTTON_SECONDARY)) { mInContextClick = false; mIgnoreNextUpEvent = true; } break; } return false; }
场景4 5 手势cancel和tap cancel的时候
private void cancel() { mHandler.removeMessages(SHOW_PRESS); mHandler.removeMessages(LONG_PRESS); mHandler.removeMessages(TAP); mVelocityTracker.recycle(); mVelocityTracker = null; mIsDoubleTapping = false; mStillDown = false; mAlwaysInTapRegion = false; mAlwaysInBiggerTapRegion = false; mDeferConfirmSingleTap = false; mInLongPress = false; mInContextClick = false; mIgnoreNextUpEvent = false; } private void cancelTaps() { mHandler.removeMessages(SHOW_PRESS); mHandler.removeMessages(LONG_PRESS); mHandler.removeMessages(TAP); mIsDoubleTapping = false; mAlwaysInTapRegion = false; mAlwaysInBiggerTapRegion = false; mDeferConfirmSingleTap = false; mInLongPress = false; mInContextClick = false; mIgnoreNextUpEvent = false; }
阅读全文
0 0
- Android手势 怎么样才算长按(GestureDetector源码)
- Android GestureDetector手势识别
- android 手势操作GestureDetector
- Android GestureDetector 手势基础
- Android GestureDetector 手势基础
- android 手势操作GestureDetector
- Android GestureDetector 手势基础
- Android GestureDetector 手势检测
- android 手势操作GestureDetector
- GestureDetector android 手势识别
- Android 手势识别--GestureDetector
- Android : GestureDetector手势检测
- Android 手势操作GestureDetector
- Android-----手势识别GestureDetector
- Android-GestureDetector手势滑动
- Android手势检测GestureDetector
- Android GestureDetector手势识别
- Android手势GestureDetector
- 使用浏览器扩展插件提取百度云的真实链接
- PHP If...Else
- linux上的free命令
- 向右收缩和展开div(2)
- 群智能优化算法之遗传、粒子群、进化算法
- Android手势 怎么样才算长按(GestureDetector源码)
- 变量指针和地址之间的关系
- 货币的时间价值
- linux下创建用户线程和内核线程
- B/S和C/S的区别
- POJ3468 A Simple Problem with Integers 【线段树/BIT】
- NOIP 2011 Senior 4
- Java中Properties和文件流使用实例
- 通过设备符号连接打开设备 句柄得到设备名_ZwOpenSymbolicLinkObject_ZwQuerySymbolicLinkObject