android 中view 的OnTouchListener和OnClickListener的区别

来源:互联网 发布:手机版数据库软件 编辑:程序博客网 时间:2024/06/05 16:23

有时候会迷惑,OnTouchListener和OnClickListener究竟有什么区别。 通过源码分析一下。

一,OnTouchListener的触发逻辑

代码在View类 中

    public boolean dispatchTouchEvent(MotionEvent event) {        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onTouchEvent(event, 0);        }        if (onFilterTouchEventForSecurity(event)) {            //noinspection SimplifiableIfStatement            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED                    && li.mOnTouchListener.onTouch(this, event)) {                return true;            }            if (onTouchEvent(event)) {                return true;            }        }        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);        }        return false;    }

分发touch事件时 先判断mOnTouchListener.onTouch() 是否处理了 事件,如果方法返回true(处理了),则不向下传递。

所以OnTouchListener 的触发时机是:手指一触摸就会触发。 action_down的时候就会触发。而且touchListener的字面意思"触碰监听"也比较贴切 。


二,OnClickListener的触发逻辑

代码也在View类 中

public boolean onTouchEvent(MotionEvent event) {...if (((viewFlags & CLICKABLE) == CLICKABLE ||                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {            switch (event.getAction()) {                case MotionEvent.ACTION_UP:                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {                        // take focus if we don't have it already and we should in                        // touch mode.                        boolean focusTaken = false;                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {                            focusTaken = requestFocus();                        }                        if (prepressed) {                            // The button is being released before we actually                            // showed it as pressed.  Make it show the pressed                            // state now (before scheduling the click) to ensure                            // the user sees it.                            setPressed(true);                       }                        if (!mHasPerformedLongPress) {                            // This is a tap, so remove the longpress check                            removeLongPressCallback();                            // Only perform take click actions if we were in the pressed state                            if (!focusTaken) {                                // Use a Runnable and post this rather than calling                                // performClick directly. This lets other visual state                                // of the view update before click actions start.                                if (mPerformClick == null) {                                    mPerformClick = new PerformClick();                                }                                if (!post(mPerformClick)) {                                    performClick();//触发点                                }                            }                        }...}


下面看触发点performClick()

    public boolean performClick() {        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);        ListenerInfo li = mListenerInfo;        if (li != null && li.mOnClickListener != null) {            playSoundEffect(SoundEffectConstants.CLICK);            li.mOnClickListener.onClick(this);//触发点击事件            return true;        }        return false;    }


在onTouch()的事件处理的逻辑中,手指抬起 action_up 时,符合click的条件,则触发mOnClickListener的逻辑。


总结:

OnTouchListener的触发点:action_down 手指按下时

OnClickListener的触发点:action_up 手指抬起时

OnTouchListener 处理逻辑在OnClickListener之前,  所以OnTouchListener 的onTouch()如果返回true, 则 onTouchEvent ()中所有逻辑失效,当然OnClickListener也不会触发。




0 0
原创粉丝点击