Android事件分发机制(1)

onTouch和onClick

  • 设置view的监听
myView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(tag, "onClick");
            }
        });

        myView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.e(tag,"onTouch");
                return false;
            }
        });

点击view打印log如下:

01-19 05:04:02.188 5013-5013/com.list E/MainActivity: onTouch
01-19 05:04:02.255 5013-5013/com.list E/MainActivity: onTouch
01-19 05:04:02.256 5013-5013/com.list E/MainActivity: onClick

可以知道先执行的onTouch事件 然后执行onClick事件

  • 如果将onTouch返回true
01-19 05:13:08.183 5661-5661/com.list E/MainActivity: onTouch
01-19 05:13:08.228 5661-5661/com.list E/MainActivity: onTouch

结果只执行了onTouch未执行onClick

  • 每次事件都会首先调用dispatchTouchEvent 看一下主要的代码
 public boolean dispatchTouchEvent(MotionEvent event) {
        // If the event should be handled by accessibility focus first.
        ...

        boolean result = false;

       ...

        if (onFilterTouchEventForSecurity(event)) {
            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
                result = true;
            }
            //noinspection SimplifiableIfStatement
            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;
            }
        }

        if (!result && mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }

        // Clean up after nested scrolls if this is the end of a gesture;
        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
        // of the gesture.
        if (actionMasked == MotionEvent.ACTION_UP ||
                actionMasked == MotionEvent.ACTION_CANCEL ||
                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
            stopNestedScroll();
        }

        return result;
    }

方法内第一行写到 // If the event should be handled by accessibility focus first.
意思就是每次事件发生都会先走此方法。
方法内定义了 result 变量来判断事件是否需要拦截默认是false
接下来

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

li 是我们在setOnTouchListener的时候赋值

 public void setOnTouchListener(OnTouchListener l) {
        getListenerInfo().mOnTouchListener = l;
    }

当我们return true的时候

li.mOnTouchListener.onTouch(this, event) = true

result赋值为true , 接下来下面的代码if条件不成立 onTouchEvent就不会被调用

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

如果我们return false的时候将会走到onTouchEvent方法

if (mPerformClick == null) {
       mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
       performClick();
 }

当case MotionEvent.ACTION_UP:的时候会调用performClick();

public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        notifyEnterOrExitForAutoFillIfNeeded(true);

        return result;
    }

在performClick()中调用了 li.mOnClickListener.onClick(this);回调到我们设置的onClickListener方法;
然后返回result;
然后上面if判断的方法

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

重新将result设置为true接下来的方法将不会执行 到最后返回result。

所以onTouch优先于onClick

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值