【android】点击touch事件流程分析

1、onTouch和onTouchEvent的区别

public boolean dispatchTouchEvent(MotionEvent event) {
        if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
            return true;
        }
        return onTouchEvent(event);
    }


1、如果dispatchTouchEvent返回值为true则本次事件被系统消耗掉(就是被控件处理了), 然后一个新的事件会被传入(如down事件返回true,则后续的move、up等事件也将被系统传入进行处理,否则move、up等事件不会响应)

2、如果dispatchTouchEvent返回值为false,则不会有新的事件被传入。

3、如果onTouch() return true则代表代码1中将不会执行 return onTouchEvent(event);语句,这也就是说这次系统事件会被消耗掉,将会再次执行dispatchTouchEvent这个方法。

4、如果onTouch() return false则代表会执行onTouchEvent(event);这个方法,本次事件是否会被消耗掉将取决于onTouchEvent的返回值。

以上说的情况适用于View对象而不是ViewGroup对象,ViewGroup对象下次再分析

2、dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()

onInterceptTouchEvent()用于处理事件并改变事件的传递方向。返回值为false时事件会传递给子控件的onInterceptTouchEvent();
返回值为true时事件会传递给当前控件的onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。

onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。

由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1.       down事件首先会传递到onInterceptTouchEvent()方法
2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5.       如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

onInterceptTouchEvent返回值只是决定了是要把事件传递给自身的onTouch事件还是传递给子组件的onTouch事件。返回false表示没有消费完将传递个子组件的onTouch方法,返回true表示自身消费此事件,将传递给自身的onTouch方法而不会传递给子组件的onTouch方法了。


dispatchTouchEvent是处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行

super.dispatchTouchEvent(ev),事件向下分发。

    onInterceptTouchEventViewGroup提供的方法,默认返回false,返回true表示拦截。

    onTouchEvent是View中提供的方法,ViewGroup也有这个方法,view中不提供onInterceptTouchEvent。view中默认返回true,表示消费了这个事件。


View里,有两个回调函数 :

  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onTouchEvent(MotionEvent ev);   

ViewGroup里,有三个回调函数 :

  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onInterceptTouchEvent(MotionEvent ev);    
  3. public boolean onTouchEvent(MotionEvent ev);  


在Activity里,有两个回调函数 :

  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onTouchEvent(MotionEvent ev);    


    Android中默认情况下事件传递是由最终的view的接收到,传递过程是从父布局到子布局,也就是从Activity到ViewGroup到View的过程,默认情况,ViewGroup起到的是透传作用。Android中事件传递过程(按箭头方向)如下图,图片来自[qiushuiqifei],谢谢[qiushuiqifei]整理。



  

    触摸事件是一连串ACTION_DOWN,ACTION_MOVE..MOVE…MOVE、最后ACTION_UP,触摸事件还有ACTION_CANCEL事件。事件都是从ACTION_DOWN开始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,执行super.dispatchTouchEvent(ev),事件向下分发。

    dispatchTouchEvent()返回true,后续事件(ACTION_MOVE、ACTION_UP)会再传递,如果返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。

3、onTouchEvent,onClick,onLongClick

Android中,onClickonLongClick的触发是和ACTION_DOWNACTION_UP相关的,在时序上,如果我们在一个View中同时覆写了onClickonLongClickonTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWNACTION_UP事件的,其次才可能触发onClick或者onLongClick。可以看到,Click的触发是在系统捕捉到ACTION_UP后发生并由performClick()执行的,performClick里会调用先前注册的监听器的onClick()方法,而LongClick的触发则是从ACTION_DOWN开始,由postCheckForLongClick()方法完成。从实现中可以看到onClick()onLongClick()方法是由ACTION_DOWNACTION_UP事件捕捉后根据各种情况最终确定是否触发的,也就是说如果我们在一个Activity或者View中同时监听或者覆写了onClick(),onLongClick()onTouchEvent()方法,并不意味着只会发生其中一种。

要弄清楚这个问题只要理解Android对事件处理的所谓消费(consume)概念即可,一个用户的操作会被传递到不同的View控件和同一个控件的不同监听方法处理,任何一个接收并处理了该次事件的方法如果在处理完后返回了true,那么该次event就算被完全处理了,其他的View或者监听方法就不会再有机会处理该event了。

     onLongClick的发生是由单独的线程完成的,并且在ACTION_UP之前,而onClick的发生是在ACTION_UP后,因此同一次用户touch操作就有可能既发生onLongClick又发生onClick。这样是不是不可思议?所以及时向系统表示“我已经完全处理(消费)了用户的此次操作”,是很重要的事情。例如,我们如果在onLongClick()方法的最后return true,那么onClick事件就没有机会被触发了。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值