android事件分发机制的详解

android事件分发机制的详解

为什么要使用事件分发?

##在很多情况下,布局复杂的界面,由于有很多的控件重叠摆放在一起,这就出现了点击事件的重复性,在开发中经常遇到点击某个子控件,父控件的点击事件需要屏蔽掉,这时候就需要用到事件分发机制来协调处理。

事件分发机制的分发和消费方向

事件分发方向

事件分发方向:DecorView->phoneWindow->Activity->ViewGroup->View

事件消费方向

事件消费方向(自向而上):View->ViewGroup->Activity->PhoneWindow->DecorView;流程图这里我就不画了,因为大家都是有一定经验的人。

demo目录结构

目录结构

demo的介绍

项目结构很简单,项目最上层的父类使用的Activity,然后用activity中包含一个ViewGroup的LinearLayout,子控件button做最后的点击事件处理,项目使用起来也比较简单,比如LinearLayout下的有三个事件方dispatchTouchEvent(),onInterceptTouchEvent(),onTouchEvent()三个方法;在手机显示的是设置每个方法的返回值,通过弹出listPopwindow进行返回值的设置,然后需要打开androidstudio日志打印点击事件的方法执行的顺序和哪些方法调用。

项目的讲解

在activity这个最上级的窗口中,重写了dispatchTouchEvent()、onTouchEvent()两个方法,这两个方法的返回值,暂时都继承父类的方法,因为如果在activity的dispatchTouchEvent()方法中返回false/true都只会调用一次activity的dispatchTouchEvent方法,无法把事件传递下去了。只会传递到更上级去了。
现在关键还是从LineaLayout控件中的方法讲解在这里插入图片描述
1.当LinearLayout控件中的dispatchTouchEvent()方法中返回参数为“true”的时候,分别执行的是Activity中的dispatchTouchEvent方法,LinearLayout中的dispatchTouchEvent,其它的是重复打印的,所以当ViewGroup的dispatchTouchEvent方法返回值是“true”的时候,意思不是事件继续分发下去,而是自行处理,这和我以前理解的有些出入。
2.当LinearLayout控件中的dispatchTouchEvent方法中返回参数为"false"的时候,如下图所示
在这里插入图片描述
执行的顺序为:Activity的dispatchTouchEvent方法,LineaLayout的dispatchTouchEvent,最后执行activity的onTouchEvent()方法;以此我们可以看出当LinearLayout的dispatchTouchEvent返回值为“false”,不进行分发下去,也就是连onTouchEvent方法也是交给上级处理。
3.当LineaLayout的dispatchTouchEvent方法返回值为super.dispatchTouchEvent(ev)的时候,如下图所示
在这里插入图片描述
从上述截图可以看出分发方法还是从activity的dispatchTouchEvent方法开始执行,再调用LineaLayout的dispatchTouchEvent方法,接着调用onInterceptTouchEvent方法,表示是否拦截当前的点击方法,如果onInterceptTouchEvent返回的是false/super方法就表示点击事件不拦截,分发给button子控件,所以就会调用button的dispatchTouchEvent方法和onTouchEvent方法。
这时候就要考虑button中的两个分发方法的返回值了:
1.如果button中的dispatchTouchEvent方法中返回true,如下图所示:
在这里插入图片描述
走的几个方法如下:activity的dispatchTouchEvent方法,LineaLayout的dispatchTouchEvent方法,LineaLayout的onInterceptTouchEvent方法,最后只会执行button的dispatchTouchEvent()方法,因为button中dispatchTouchEvent返回的参数是true,也就相当于这个事件链中断了,不会再分发下去了,也不会沿上级传递了。
2.如果button中的dispatchTouchEvent方法中返回false,如下图所示:
在这里插入图片描述
前面三个方法还是一样的执行,关键看后面两个方法,先执行的是button的dispatchTouchEvent方法,因为在button的dispatchTouchEvent方法中返回了false,表示当前的事件不分发给当前的button下的onTouchEvent方法了,所以button的onTouchEvent方法就不执行了,当时事件并没有中断,可以往上传递,所以就只能执行button的上一级父类的onTouchEvent方法了,也就是LinearLayout的onTouchEvent方法了。
3.如果button中的dispatchTouchEvent方法中返回super,如下图所示:
在这里插入图片描述
同样执行五个方法,前面三个方法和上面一样,这时候会调用button的dispatchTouchEvent,因为是super的,所以事件默认是继续分发下去,如果button的dispatchTouchEvent是super/true的,默认就是自己消费掉了,不会再向上级传递了。反之button的dispatchTouchEvent是false的,自己不完全消费掉,还是可以往上级传递,调用LinearLayout的onTouchEvent方法,如下图所示:
在这里插入图片描述
项目到这,基本就差不多。很好理解把!好了多了也不说了,想了解详情可以下载下demo,自己测试一下就什么都懂了。
链接地址:事件分发demo链接地址

总结

总之,如果一个控件中,不管是Activity还是ViewGroup,view的dispatchTouchEvent方法中返回true,就表示事件在当前控件断掉了,不会向上级传递也不会当前控件消费;一个ViewGroup/View/Activity的dispatchTouchEvent方法如果返回false,意思就是事件不再当前的控件分发下去,就会交给上一级的父类onTouchEvent方法进行处理;一个ViewGroup的onInterceptTouchEvent拦截方法,如果返回值为true,拦截掉当前的事件,交由自己的onTouchEvent方法或者父类的onTouchEvent方法处理,如果当前的ViewGroup的onTouchEvent方法返回值为super/false,表示当前的控件不完全消费掉当前的点击事件,也会交由上级的onTouchEvent方法处理,反之,返回true就只能调用当前的ViewGroup的onTouchEvent方法,如果ViewGroup的onInterceptTouchEvent拦截方法返回值false/super,都表示不拦截当前要传递的事件,事件往下级传递,最终如果子类的onTouchEvent方法中返回super/true,表示事件处理完毕,整个流程结束,如果是返回false,事件交由上一级处理,如果上一级的onTouchEvent方法中还是返回false,继续交由上级处理,依次类推…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值