事件分发机制的原理总结

触摸事件相关方法:

ViewGroup

•dispatchTouchEvent(MotionEvent)         用于分发touch事件

•onInterceptTouchEvent(MotionEvent)     用于是否中断touch事件,true中断,false不中断,默认false

•onTouchEvent(MotionEvent)                    用于处理touch事件,true消费事件,false不消费,默认false

 

View、Activity

•dispatchTouchEvent(MotionEvent)         用于分发touch事件

•onTouchEvent(MotionEvent)                    用于处理touch事件

 

下面用一张图来概括Activity、ViewGroup、View之间的事件传递和消费流程

 

总结:

1.touch事件的传递其实就是一连续的方法调用.由activity的dispatchTouchEvent方法开始调用
2.消费了Down事件的view称为目标View,目标View可以接收后续的事件,非目标View不可以接收后续事件
3.Down事件如果没有任何View消费,则后续事件不再传递,直接由Activity的onTouchEvent方法处理,所以,想要处理其他事件首先要消费Down事件,即返回true

拦截:

1)如果Down事件拦截,则把当前事件交给自己的onTouchEvent方法处理,如果此方法不消费Down事件,则事件丢失,后续的事件交由Activity的onTouchEvent方法处理

2)如果Down事件不拦截而其他事件拦截,则Down事件自己不处理,分发给子View处理Down事件,且会传一个Cancel事件给目标View,后续的事件就会交给自己的onTouchEvent方法处理,此时拦截该事件的view就变成了目标view,虽然没有消费Down事件

3)如果Down事件不拦截,在事件分发返回后,如果Down事件没有被子View消费,那么会把事件交给自己的onTouchEvnet方法处理,如果自己也不处理就会继续向上返回,谁处理谁消费,如果向上都不处理,则回到Activity处理。

4)如果不拦截事件,且能接收到事件(dispatchTouchEvent和onInterceptTouchEvent能收到),则说明有目标View的存在,在事件分发方法返回后,是不会把事件交给自己的onTouchEvent方法处理,因为自己不是目标View,即使目标View在处理Move,Up事件时返回了false.

5.Activity不管有无目标View,也不管是Down还是Move,Up事件,只要分发方法返回后,如果事件没有被消费,则交给自己的onTouchEvent方法处理

6.可以调用getParent().requestDisallowInterceptTouchEvent(true)方法来请求父View禁止拦截事件,这个方法会递归的请求所有的父View禁止拦截事件.

7.如果2个View并没有包含关系,而是重叠关系,则处于上面的View先拿到事件,如果消费了,则事件不会传递给另一个View

8.容器一般都是调用ViewGroup的dispatchTouchEvent方法进行事件分发,其他类一般是调用View类的dispatchEvent方法进行事件分发;通常默认的onInterceptTouchEvent,onTouchEvent方法都是返回false.

9.所有的事件分发都是调用super.dispatchTouchEvent(ev)完成的,所以如果不调用这句代码则事件中止传递。但是要中止事件传递一般不会这么做,一般是在onInterceptTouchEvent(MotionEvent) 方法中处理,如果该方法返回true则中止。既然dispatchTouchEvent(ev)方法可以中止事件传递,为什么还要设计一个onInterceptTouchEvent(MotionEvent) 方法呢? 因为子View可以请求父View不要拦截事件,如ListView是可以上下滑动的,当处于滑动状态时候就会请求禁止父View的拦截触摸事件方法,让ListView可以一直获取到touch事件进行滚动。假设这个时候父View又想响应触摸事件怎么办?可以写到dispatchTouchEvent方法中,因为事件是先传到这个方法,然后再传递给ListView的。

10.如果父View的onInterceptTouchEvent方法返回true,则事件会直接传递到父View的onTouchEvent方法处理,此时如果父View的onTouchEvent方法返回false或者super的话,则事件会终止向下分发,直接向上返回到调用处;而如果返回true则直接消费事件,不会向上返回了。因此父View一旦拦截了事件,子View就收不到任何事件了。

应用技巧:

1)父类的onTouchEvent方法要想执行,要么是等所有的子View都不消费Down事件,要么是父View把事件拦截.

2)如果子View消费了Down事件,而父View又不想拦截,却又想处理这个事件,则父View可以通过onInterceptTouchE方法或者dispatchTouchEvent方法来处理Touch事件

3)如果子View请求了禁止父View拦截事件,但父View又还想拦截的话,可以在父View的dispatchTouchEvent方法中不调用super.dispatcheTouchEvent方法则把事件拦截了.

4)如果在Activity中一定要响应一些触摸事件,又怕事件传递后被消费了,可以直接在Activity的dispatchTouchEvent方法中处理即可.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值