TouchEvent事件的传递


onInterceptTouchEvent & onTouchEvent
注意onTouchEvent是自上而下传递,而onInterceptTouchEvent却是由下而上传递的。

1.如果onInterceptTouchEvent 返回false,则继续向上传递,不传递给自己的onTouchEvent,同时后续事件仍会经过。
2.如果onInterceptTouchEvent 返回true,则传递给自己的onTouchEvent, 并且不接收后续事件,直接传递给自己的onTouchEvent。
    注意,底层传来的事件,依然会通过底层的 onInterceptTouchEvent  。
3.如果onTouchEvent 返回false,表示未消费该事件,事件继续向下传递。
4.如果onTouchEvent 返回true,表示已消费该事件,并且后续事件仍会发送至此处。
    注意,底层传来的事件,依然会通过底层的 onInterceptTouchEvent  。到达该层后,直接给onTouchEvent,而不经过onInterceptTouchEvent。

总结,onInterceptTouchEvent 和 onTouchEvent ,若返回false,表示仍旧按照原定路径传递;若返回true,表示路径会有更改。
若onInterceptTouchEvent返回true,表示不继续向上传递,直接传给自己的onTouchEvent,且后续不经过自己的onInterceptTouchEvent,直接给onTouchEvent.

若onTouchEvent返回true,表示不继续向下传递,此处消费完成,且后续事件不经过自己的onInterceptTouchEvent,直接给onTouchEvent.


预定路径如下:
                onInterceptTouchEvent             onTouchEvent
child                                                     →                                   true          →    End
                  false      ↑                                                        ↓  false

parent2                                 true          →                                  true          →    End

                  false      ↑                                                        ↓  false
parent1                                 true          →               


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

    1.onInterceptTouchEvent首先会接到事件:
        如果onInterceptTouchEvent返回false,则向上传递,并且接下来的所有事件都要经过onInterceptTouchEvent处理。
        如果onInterceptTouchEvent返回true,将不会再接受接下来的事件,并且当前事件交给自己的onTouchEvent处理。
    2.事件可能会被子view或者本身的onTouchEvent处理。
        onTouchEvent返回true,onInterceptTouchEvent不再接收到事件,所有的touch处理都将发生在onTouchEvent.
        onTouchEvent返回false,则表示未消费,继续向下传递。
    
按键消息与触屏消息
Android按键事件处理主要在View和Activity两个级别。
按键事件的处理机制如下:
1、默认情况下,如果没有View获得焦点,事件将传递给Activity处理。
2、如果View获得焦点,事件首先传递到View的回调方法中。view回调方法返回false,事件继续传递到Activity处理。反之,事件不会继续传递。
PS:使用View.SetFocusable(true)设置可以获得焦点。
需要注意的是:
1、按键的onKeyDown和onKeyUp是相互独立的,不会相互影响。
2、无论是View还是Activity中,建议重写事件回调方法时,只对处理过的按键返回true,没有处理的事件应该调用其父类方法。

Android中提供了ViewGroup、View、Activity三个等级的Touch事件处理。也就是说,这三个地方都有事件回调方法。
整体上看,事件传递顺序为ViewGroup::onInterceptTouchEvent() –> ViewGroup或View的onTouchEvent() –> Activity::onTouchEvent()

由于上面每个事件回调方法的返回值不同,导致事件本身及顺序发生微妙变化。


  onTouchEvent && onClick && onLongClick 的调用顺序
上文我们讨论了onTouchEvent的处理机制。onTouchEvent中要处理的最常用的3个事件就是:ACTION_DOWN、ACTION_MOVE、ACTION_UP。ACTION_DOWN事件作为起始事件,它的重要性是要超过ACTION_MOVE和ACTION_UP的,如果发生了ACTION_MOVE或者ACTION_UP,那么一定曾经发生了ACTION_DOWN。
onClick、onLongClick的触发是和ACTION_DOWN及ACTION_UP相关的,在时序上,如果我们在一个View中同时覆写了onClick、onLongClick及onTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能触发onClick或者onLongClick。主要的逻辑在View.java中的onTouchEvent方法中体现:Click的触发是在系统捕捉到ACTION_UP后发生并由performClick()执行的,performClick里会调用先前注册的监听器的onClick()方法;LongClick的触发则是从ACTION_DOWN开始,由postCheckForLongClick()方法完成,在ACTION_DOWN事件被捕捉后,系统会开始触发一个postDelayed操作,delay的时间后会触发CheckForLongPress线程的执行,如果各种条件都满足,那么在CheckForLongPress中执行performLongClick(),在这个方法中将调用onLongClick().
    一个用户的操作会被传递到不同的View控件和同一个控件的不同监听方法处理,任何一个接收并处理了该次事件的方法如果在处理完后返回了true,那么该次event就算被完全处理了,其他的View或者监听方法就不会再有机会处理该event了。
    onLongClick的发生是由单独的线程完成的,并且在ACTION_UP之前,而onClick的发生是在ACTION_UP后,因此同一次用户touch操作就有可能既发生onLongClick又发生onClick(若之前onLongClick返回false)。所以及时向系统表示“我已经完全处理(消费)了用户的此次操作”,是很重要的事情。如果在onLongClick()方法的最后return true,那么onClick事件就没有机会被触发了。
一、一个onClick被触发的基本时序:
onTouchEvent (ACTION_DOWN)
onTouchEvent (ACTION_UP)
onClick()
在ACTION_UP之后才会触发onClick()
二、一个onLongClick被触发的基本时序:
onTouchEvent (ACTION_DOWN)
onLongClick()
onTouch (ACTION_UP)
在保持按下状态一定时间后会触发onLongClick(),之后发生ACTION_UP。
三、onClick和onLongClick同时存在的基本时序
在onLongClick()方法return false情况下,一次触碰操作基本时序:
onTouchEvent (ACTION_DOWN)
onLongClick()
onTouchEvent (ACTION_UP)
onClick()
onLongClick()方法return false情况下,onLongClick发生在ACTION_UP之前,onClick发生在ACTION_UP后,同一次touch操作就既发生onLongClick()又发生onClick()。
如果在onLongClick()方法中return true,那么onClick事件就没有机会被触发。


onTouch与onTouchEvent
onTouch是View的onTouchListener接口中的方法。
众所周知,在android的事件处理中,有两种处理方式:基于监听的事件处理和基于回调的事件处理。
我们之前讨论的onTouchEvent,onInterceptTouchEvent,onClick,onLongClick都是基于回调。
而onTouch则是基于监听的事件处理方式。其触发的位置是早于基于回调的事件处理onTouchEvent的,
但是会在onInterceptTouchEvent之后。


dispatchTouchEvent
每次view的dispatchTouchEvent分发消息的时候,先判断是不是有监听器的存在,然后条件允许的情况下再分发给回调方法。

ViewGroup重写了该方法,在dispatchTouchEvent中判断是否需要拦截,是的话调用onInterceptTouchEvent.之后再根据情况判断是调用父类view.dispatchTouchEvent还是调用子控件child.dispatchTouchEvent.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值