Android开发事件分发,完全弄个明白

首先是事件分发的过程,当手触摸到屏幕时是activity的dispatchTouchEvent先获得事件,然后分发给 layout的最外层viewgroup,如果事件没有被拦截,这时ViewGroup会遍历子view,如果事件源的位置在子view上,那么看子view是否会处理事件,如果不处理再传递给下层的子view,如果子view都没有处理,事件会再向上传递给ViewGroup,如果事件最终都没有被消费,那么事件最终还会回到activity的onTouchEvent方法中最终来处理,那么后续的事件最外层的layout也不会再接受到了。

一、对view来说

1、dispatchTouchEvent,理解为是否接收后续事件。其返回值:

true——该控件接收后续事件源,后续仅执行这一个方法,但不会有相应的事件反馈,如触摸事件、点
击事件,即不执行 onTouchListener,onClickListener或onTouchEvent等方法。

false——该控件不会接收到后续事件了,该方法也执行这一次。

super.dispatchTouchEvent——是否接收后续事件(手从屏幕抬起之前的事件,包括抬起)由后续的结果 决定。改方法会先调用onTouchListener(如果设置了监听器),如果返回值为true,即消费 了事件,该方法也会返回true,即要接收后续事件,后续事件在监听器中处理,不会再调用onTouchEvent,也不会有点击事件的回调。如果onTouchListener的返回值为false或是没有设置触摸监听,该方法会调onTouchEvent,其返回值也作为该方法的返回值。

2、onTouchEvent(),事件处理的回调,其返回值代表了该事件是否被消费。
true——消费了该事件,后续的事件也在该方法中处理,没有点击事件的回调

false——不消费该事件,事件向上传递,后续不会再收到事件,没有点击事件的回调

super.onTouchEvent——如果设置了点击事件监听,该方法会回调点击监听。

对于一些控件来说,其默认的onTouchevent的返回值也不同,如Textview的默认返回为false,当其设置了clickListener或onTouchListener的返回值为true后就返回true,Button的默认返回值为true,一般容器类控件的默认返回值为false,Scrollview的默认返回为true。
二、对ViewGroup来说

1、dispatchTouchEvent,事件分发。
有两个条件来判断是否拦截跟分发: a、是否允许拦截(可通过方法requestDisallowInterceptTouchEvent来设置) b、是否拦截了(通过方法onInterceptTouchEvent的值来确定)。
只有当允许拦截并且拦截了事件,该事件才会直接到达ViewGroup的ontouchevent中,否则事件会分 发到 子view中。

2、onInterceptTouchEvent,事件是否拦截。当返回值为true是表明拦截了该事件,该事件会直接到自己的
onTouchEvent方法中,并且后续的事件子view也不会再获得。

3、onTouchEvent,事件处理。当自己拦截了事件或者子view没有能够消费事件时,事件回到达该方法中,
这是ViewGroup就跟一个普通的view一样就要自己来处理事件,但是否处理由其返回值决定。

4、requestDisallowInterceptTouchEvent,设置是否允许拦截事件。如果设置为true,即不允许拦截事
件,那么就会跳过onInterceptTouchEvent方法而直接进行事件分发。

例:当手触摸屏幕时,Activity的dispatchTouchEvent先将touch事件分发给最外层的ViewGroup,执行
ViewGroup的dispatch,这时如果ViewGroup没有进行事件拦截,事件会传递给子view,执行自view的dispatch–>ontouchListener–>ouTouchEvent–>onClickListener,如果子view都没有进行事件处理,则返回ViewGroup执行onTouchListener–>onTouchEvent–>onClickListener,任何一个方法返回true,即表明处理了事件,否则最终回到了Activity的onTouchEvent中。如果ViewGroup中的dispatchTouchEvent方法中,事件event.getAction() == MotionEvent.ACTION_DOWN时,onInterceptTouchEvent的返回值为
true,即拦截了事件,那么后续事件子view都不会再获得;如果在此时返回false而在
event.getAction() == MotionEvent.ACTION_MOVE时返回true,这是如果想要在后续事件中子view也要获得事件,可在子view的dispatchTouchEvent中执行getParent().requestDisallowInterceptTouchEvent(true),以此将ViewGroup的是否允许拦截变量设置为不允许拦截,这样就不会判断是否拦截了事件而直接将事件分发。

三、对Activity来说

1、dispatchTouchEvent,最先获得事件并分发给最外层的ViewGroup,其无论返回true或false,
ViewGroup都不收接收到事件,也不会将事件传给自己的onTouchEvent,只有返回
super.dispatchTouchEvent时事件才会正常传递。

2、onTouchEvent,事件处理。如果ViewGroup跟子view都没有将事件处理掉,那么事件最终会回传给自
己的该方法,而此时无论该方法的返回值为true或false后续的事件都在该方法中处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值