且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

android View中如何判断长按事件

更新时间:2022-09-06 10:03:59

一、如果用户在获得焦点的VIEW上按KEYCODE_DPAD_CENTER或KEYCODE_ENTER键,即OK键后,在VIEW的onKeyDown方法中会开启一个延迟线程,在延迟线程中会去回调onLongClick()方法,代码如下:

在如下代码中开始延迟线程:

  1. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  2.        boolean result = false;  
  3.   
  4.        switch (keyCode) {  
  5.            case KeyEvent.KEYCODE_DPAD_CENTER:  
  6.            case KeyEvent.KEYCODE_ENTER: {  
  7.                if ((mViewFlags & ENABLED_MASK) == DISABLED) {  
  8.                    return true;  
  9.                }  
  10.                // Long clickable items don't necessarily have to be clickable   
  11.                if (((mViewFlags & CLICKABLE) == CLICKABLE ||  
  12.                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&  
  13.                        (event.getRepeatCount() == 0)) {  
  14.                    setPressed(true);  
  15.                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {  
  16.                        postCheckForLongClick(0);//在这里开启延迟线程   
  17.                    }  
  18.                    return true;  
  19.                }  
  20.                break;  
  21.            }  
  22.        }  
  23.        return result;  
  24.    }  
 public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean result = false;

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_ENTER: {
                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                    return true;
                }
                // Long clickable items don't necessarily have to be clickable
                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
                        (event.getRepeatCount() == 0)) {
                    setPressed(true);
                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
                        postCheckForLongClick(0);//在这里开启延迟线程
                    }
                    return true;
                }
                break;
            }
        }
        return result;
    }


延迟线程代码如下:

  1. class CheckForLongPress implements Runnable {  
  2.   
  3.         private int mOriginalWindowAttachCount;  
  4.   
  5.         public void run() {  
  6.             if (isPressed() && (mParent != null)  
  7.                     && mOriginalWindowAttachCount == mWindowAttachCount) {  
  8.                 if (performLongClick()) { //这里回调onLongClick()方法   
  9.                     mHasPerformedLongPress = true;  
  10.                 }  
  11.             }  
  12.         }  
  13.   
  14.         public void rememberWindowAttachCount() {  
  15.             mOriginalWindowAttachCount = mWindowAttachCount;  
  16.         }  
  17.     }  
class CheckForLongPress implements Runnable {

        private int mOriginalWindowAttachCount;

        public void run() {
            if (isPressed() && (mParent != null)
                    && mOriginalWindowAttachCount == mWindowAttachCount) {
                if (performLongClick()) { //这里回调onLongClick()方法
                    mHasPerformedLongPress = true;
                }
            }
        }

        public void rememberWindowAttachCount() {
            mOriginalWindowAttachCount = mWindowAttachCount;
        }
    }

二、如果用户在触摸屏上长按某个VIEW,VIEW中首先会检测在这个触摸点移动没,如果没有移动再开启一个延迟线程去回调onLongClick()方法,代码如下:

在View中的onTouchEvent中的DOWN事件中:

  1. case MotionEvent.ACTION_DOWN:  
  2.                     if (mPendingCheckForTap == null) {  
  3.                         mPendingCheckForTap = new CheckForTap();  
  4.                     }  
  5.                     mPrivateFlags |= PREPRESSED;  
  6.                     mHasPerformedLongPress = false;  
  7.                     postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());//开始延迟线程检测触摸点移动没   
  8.                     break;  
case MotionEvent.ACTION_DOWN:
                    if (mPendingCheckForTap == null) {
                        mPendingCheckForTap = new CheckForTap();
                    }
                    mPrivateFlags |= PREPRESSED;
                    mHasPerformedLongPress = false;
                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());//开始延迟线程检测触摸点移动没
                    break;

如果没有移动,则会开启一个延迟线程回调onLongClick()方法:

  1. private final class CheckForTap implements Runnable {  
  2.        public void run() {  
  3.            mPrivateFlags &= ~PREPRESSED;  
  4.            mPrivateFlags |= PRESSED;  
  5.            refreshDrawableState();  
  6.            if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {  
  7.                postCheckForLongClick(ViewConfiguration.getTapTimeout());//开启延迟线程回调onLongClick()方法   
  8.            }  
  9.        }  
  10.    }  
 private final class CheckForTap implements Runnable {
        public void run() {
            mPrivateFlags &= ~PREPRESSED;
            mPrivateFlags |= PRESSED;
            refreshDrawableState();
            if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
                postCheckForLongClick(ViewConfiguration.getTapTimeout());//开启延迟线程回调onLongClick()方法
            }
        }
    }

剩下来就和按键长按一样的处理了。


在其中要注意二个参数:

ViewConfiguration.getTapTimeout() 是用于检测触摸点有没有移动的时间,默认为115毫秒

 ViewConfiguration.getLongPressTimeout() 是用于检测是不是长按的时间,默认为500毫秒