美文网首页
事件分发-Click Touch监听器源码分析

事件分发-Click Touch监听器源码分析

作者: 杨0612 | 来源:发表于2020-05-19 11:03 被阅读0次

分析下OnClickListener,OnLongClickListener,OnTouchListener,onTouchEvent这4个方法的调用关系。
源码分析基于Android-23

1.简述方法作用

1.1 OnTouchListener以及 onTouchEvent
都是可以监听Touch事件,区别在于,前者是通过setOnTouchListener的方式来使用,后者是view的方法,重写即可,常用在自定义控件;
1.2 OnClickListener
监听点击事件;
1.3 OnLongClickListener
监听长按事件。

2.OnTouchListener onTouchEvent两者的关系

2.View.dispatchTouchEvent

(1)dispatchTouchEvent,是事件处理的入口;
(2)当设置了setOnTouchListener,那么li.mOnTouchListener就不为空,onTouch方法会被触发并且返回true,那么onTouchEvent就不会被触发;
(3)没有设置setOnTouchListener或者onTouch方法返回false,那么onTouchEvent就不会被触发;
(4)返回true比较消费了事件;
(5)可以看出mOnTouchListener onTouch方法优先级比onTouchEvent高;

public boolean dispatchTouchEvent(MotionEvent event) {
        ......
        if (onFilterTouchEventForSecurity(event)) {
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
       ......
        return result;
    }

3.OnTouchEvent OnClickListener、OnLongClickListener三者的关系

View.onTouchEvent

(1)主要看down、move、up事件的处理;
(2)down事件,如果view被滑动控件包裹,则isInScrollingContainer为true,需要通过延时任务mPendingCheckForTap判断是tap事件还是滑动事件,如果在延时时间100毫秒内没有任何滑动,则发送400毫秒延时任务执行长按,有任何滑动都将移除mPendingCheckForTap;
(3)上述(2)没有包裹在滑动控件中,则触发checkForLongClick发送500毫秒延时任务执行长按;
(4)up事件,如果长按事件没有被触发或者返回false,mHasPerformedLongPress 则为false,将移除长按任务,接着执行performClick,通过从ViewRootImpl得到的handle往主线程队列发送点击任务,等待被执行,由此可见长按事件被消费了,那么点击事件就无法执行;
(5)performClick内部就是触发li.mOnClickListener.onClick,这里就不展开了;
(6)move事件,移除tap任务removeTapCallback,如果发送了延时任务执行长按,也需要移除removeLongPressCallback;
(7)当onTouchEvent被触发,onClick、onLongClick才有可能被执行,如果onLongClick消费了时间,那么onClick将无法执行;

public boolean onTouchEvent(MotionEvent event) {
            ......
            switch (action) {
                case MotionEvent.ACTION_UP:
                        ......
                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                            removeLongPressCallback();
                            ......
                           performClick();
                        }
                    ......
                    break;

                case MotionEvent.ACTION_DOWN:
                    ......
                    if (isInScrollingContainer) {
                        if (mPendingCheckForTap == null) {
                            mPendingCheckForTap = new CheckForTap();
                        }
                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                    } else {
                        checkForLongClick(0);
                    }
                    break;

                case MotionEvent.ACTION_CANCEL:

                    removeTapCallback();
                    removeLongPressCallback();
                    ......
                    break;

                case MotionEvent.ACTION_MOVE:
                    ......
                    if (!pointInView(x, y, mTouchSlop)) {
                        removeTapCallback();
                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
                              ......
                            removeLongPressCallback();
                        }
                    }
                    break;
            }
            return true;
        }
        return false;
    }
5.总结

(1) OnTouchListener onTouch优先级比onTouchEvent高;
(2)当onTouchEvent被触发,onClick、onLongClick才有可能被执行,
(3)当onLongClick消费了事件,那么onClick将无法执行;
(4)点击事件实现,在up事件时,利用ViewRootImpl构建的handler,往主线程MessageQueue发一个runnable点击任务,等待被分发执行;
(5) 长按事件实现,发送100毫秒延时任务判断是tap还是滑动,如果是tap,则再发送400毫秒延时任务执行长按;

有分析不对的地方请指出,互相学习,谢谢哦!

相关文章

网友评论

      本文标题:事件分发-Click Touch监听器源码分析

      本文链接:https://www.haomeiwen.com/subject/ftqpohtx.html