Android View 关于OnLongClickListener

View的OnLongClickListener事件实现原理是什么,又是如何触发(postDelayed),长按时间多久呢(0.4s)?

1、通过源码我们发现View.setOnLLongClickListener()方法中:
     setLongClickable(true);
     getListenerInfo().mOnLongClickListener = l;

public void setOnLongClickListener(@Nullable OnLongClickListener l) {
        if (!isLongClickable()) {
            setLongClickable(true);
        }
        getListenerInfo().mOnLongClickListener = l;
}

2、那么它是如何触发长按监听回调的呢,通过监听我们发现它是在performLongClickInternal()触发回调的

private boolean performLongClickInternal(float x, float y) {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);

        boolean handled = false;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnLongClickListener != null) {
            //长按回调
            handled = li.mOnLongClickListener.onLongClick(View.this);
        }
        if (!handled) {
            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
        }
        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
            if (!handled) {
                handled = showLongClickTooltip((int) x, (int) y);
            }
        }
        if (handled) {
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        }
        return handled;
 }

3、那么让我来看看上层调用方法:

①、performLongClick()

public boolean performLongClick() {
        return performLongClickInternal(mLongClickX, mLongClickY);
}

②、performLongClick(float x,float y)


    public boolean performLongClick(float x, float y) {
        mLongClickX = x;
        mLongClickY = y;
        final boolean handled = performLongClick();
        mLongClickX = Float.NaN;
        mLongClickY = Float.NaN;
        return handled;
    }

4、接下来,我们继续看performLongClick(float x,float y)却在CheckForLongPress runnable 中调用,那么长按用就是view.postDelayed()吗?

①、CheckForLongPress类

private final class CheckForLongPress implements Runnable {
        private int mOriginalWindowAttachCount;
        private float mX;
        private float mY;
        private boolean mOriginalPressedState;
        /**
         * The classification of the long click being checked: one of the
         * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
         */
        private int mClassification;

        @UnsupportedAppUsage
        private CheckForLongPress() {
        }

        @Override
        public void run() {
            if ((mOriginalPressedState == isPressed()) && (mParent != null)
                    && mOriginalWindowAttachCount == mWindowAttachCount) {
                recordGestureClassification(mClassification);
                if (performLongClick(mX, mY)) {
                    mHasPerformedLongPress = true;
                }
            }
        }

        public void setAnchor(float x, float y) {
            mX = x;
            mY = y;
        }

        public void rememberWindowAttachCount() {
            mOriginalWindowAttachCount = mWindowAttachCount;
        }

        public void rememberPressedState() {
            mOriginalPressedState = isPressed();
        }

        public void setClassification(int classification) {
            mClassification = classification;
        }
    }

②、CheckForLongPress创建,确实是通过postDelayed来延迟生效的

 private void checkForLongClick(long delay, float x, float y, int classification) {
        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
            mHasPerformedLongPress = false;

            if (mPendingCheckForLongPress == null) {
                mPendingCheckForLongPress = new CheckForLongPress();
            }
            mPendingCheckForLongPress.setAnchor(x, y);
            mPendingCheckForLongPress.rememberWindowAttachCount();
            mPendingCheckForLongPress.rememberPressedState();
            mPendingCheckForLongPress.setClassification(classification);
            postDelayed(mPendingCheckForLongPress, delay);
        }
    }

③、哪些调用checkForLongClick方法呢?

④、我们发现前五都是View事件,来触发的。

⑤、那么第六个View.CheckForTap又是干什么呢?

 发现其实也是View.onTouchEvent里面的 MotionEvent.ACTION_DOWN 触发的

自此我们可以说:View.OnLongClickListener 是通过View.postDelayed()触发长按回调。

 3、触发时间

①、View.onKeyDown调用:ViewConfiguration.getLongPressTimeout()   

 public static final int DEFAULT_LONG_PRESS_TIMEOUT = 400;

 public static int getLongPressTimeout() {
        return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
                DEFAULT_LONG_PRESS_TIMEOUT);
    }

②、View.onTouchEvent()调用

MotionEvent.ACTION_DOWN 

 MotionEvent.ACTION_MOVE

通过源码我们发现,一般触发长按事件的时长围为0.4s。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值