android的触摸事件处理

android对触摸事件的处理逻辑简单概述为:从上到下传递事件,然后从下到上处理时间逻辑,其实事实我们也可以理解,在你触摸屏幕的时候,首先第一层拿到事件,然后一层一层传下去,当传到具体view,如TextViewBUtton等时,结束传递,然后开始处理。一层一层往上传,但是在传的过程中,会根据onTouchEvent

onInterceptTouchEvent(MotionEvent ev)的返回值,做不同操作吧了。下面会详细分析返回不同值的处理逻辑

触摸事件肯定由下面一系列动作 :

ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP,肯定有一个downup事件,按实际情况来讲,也肯定从在move动作,因为人的手指在点的过程,肯定会从在一定情况的移动,只是感觉不到吧了,但是程序可以知道,只是程序理解了你的这个移动,不处理。

首先说一下事件的大概流程:事件接收层(底层:硬件和软件,一般不需要了解)---->窗口管理系统 WindowMangerServicer WMS----->因为所有的窗口都是有他创建的,所有WMS知道当前活动的窗口是谁,WMS将事件交给当前活动窗口-------->当前活动窗口拿到事件,调用VIewRoot类的dispatchTouchEvent,给当前活动窗口的根view--->view开始dispatchTouchEvent事件到具体view。以下的讨论是接着这里开始详细讨论。

1.如果是具体view,(非ViewGroup),如TextView等 ,这种情况根本不存在,因为每个窗口,肯定有个rootview,及viewGroup

2.如果是ViewGroup,比如LinearLayout等。

如果是down事件,开始下面逻辑

--递归开始点-) 首先调用vieGroupdispatchTouchEvent方法,如果是down事件,则清空上次处理该事件的对象(为了处理MOVE之类的事件,做的缓存)mMotionTarget = null;

调用onInterceptTouchEvent方法,这个方法只有ViewGroup类有,具体view没有,该方法的作用是判断是否需要拦截该消息,如果返回的是true,那么消息传递结束,调用该view对象的onTouchEvent方法。如果返回的是false,说明该view没有消费事件,继续往下走

因为触摸事件是窗口坐标值,所以需要将坐标值转换为view自己的坐标体系。

转换结束后,使用for循环遍历,该view的所有子view,读取子view的坐标体系,即子view所占的大小,是个Rect对象,上下左右,拿到这个值后,根据上面转换好的坐标,判断点击的坐标是否包含在当前子view中,如果不包含,直接开始下一个子view

如果坐标包含在子view中,则调用子viewdispatchTouchEvent,如果子view还是ViewGroup类型的,那么开始从上面标有(--递归开始点-)处递归调用。如果是具体view,则调用具体viewdispatchTouchEvent,这个方法比较简单,首先判断是否通过setTouchEventListener设置值,如果设置了,那么调用onTouch方法,如果该方法返回的是ture,则直接返回,不在调用该viewOntouchEvent方法,如果返回false,则调用该viewOntouchEvent方法。并把该方法当作dispatchTouchEvent的返回者返回。

具体viewdispatchTouchEvent处理结束后,子viewdispatchTouchEvent 如果返回的是true,该view的父view会将该view对象保存到mMotionTarget,同时结束到本次down事件,如果放回的是false,则继续for循环(个人此时可以推出for循环,因为感觉没用,难道是担心有view覆盖的原因吗),开始下一个子view

--递归结束点-for结束后(由于该过程是同步的,所以在执行这个过程中不会有其他的事件发送过来),判断mMotionTarget是否为空,如果为空,说明没有找到目标子view,所以调用当前view(一定是ViewGroup对象的,而且是循环体所在的view对象)的super.dispatchTouchEvent方法,这个是View基类的,实现和具体view的处理逻辑一样,首先判断是否通过setTouchEventListener设置值,如果设置了,那么调用onTouch方法,如果该方法返回的是ture,则直接返回,不在调用该viewOntouchEvent方法,如果返回false,则调用该viewOntouchEvent方法。并把该方法当作 dispatchTouchEvent的返回者返回 ,交给该ViewGroupdispatchTouchEvent for循环(递归调用结束一个),这就说明,如果所有的子view不消费事件,那么view会消费该事件,不管onInterceptTouchEvent的返回结果是ture还是false。同时结束本次事件。

至此,一个Down事件就处理结束,处理结束后会通知WMS,此时WMS开始派发下一个事件。

如果过来的事件是move或者up事件,首先判断down处理逻辑得到mMotionTarget是否为空,也就是说down处理中,是否找到的接收事件的子view。如果为空:说明没有找到目标子view,所以调用当前view(一定是ViewGroup对象的,而且是循环体所在的view对象)的super.dispatchTouchEvent方法,这个是View基类的,实现和具体view的处理逻辑一样, 首先判断是否通过setTouchEventListener设置值,如果设置了,那么调用onTouch方法,如果该方法返回的是ture,则直接返回,不在调用该viewOntouchEvent方法,如果返回false,则调用该viewOntouchEvent方法。并把该方法当作 dispatchTouchEvent的返回者返回 ,交给该ViewGroup的 dispatchTouchEvent for循环(递归调用结束一个),这就说明,如果所有的子view不消费事件,那么view会消费该事件,不管onInterceptTouchEvent的返回结果是ture还是false。同时结束本次事件

如果不为空,这个时候mMotionTarget 的直接的直接父类只走dispatchTouchEvent事件,但是mMotionTarget 的爷爷及老爷还会走dispatchTouchEvent onInterceptTouchEvent事件,暂时没弄明白,有明白的解释一下,谢谢。那么本次的moveup事件继续由该子view处理,这样的逻辑我们可以想到,因为同一个事件,应该有同一个view处理,而不是down事件是一个view处理,moveup事件是一个view处理。所以不为空的情况下,直接由mMotionTargetdispatchTouchEvent处理去。

同时我们知道,在activity中还可以注册ontouchEventListener,那么他什么时间执行了?他执行的时间就是在view中没有找到消费该事件的view时,则交给acitivity去处理.

总结:

如果父viewonInterceptTouchEvent返回的是ture,那么子view永远拿不到touch事件,同时子viewonclick事件也不会处理,因为onclick事件是在viewontouch事件中根据条件调用的,同时如果重新viewontouchEvent方法,而没有调用super.OntouchEvent.那么onclick事件也不会处理

如果给一个view设置了onTouchEventListener,同时设置了OnclickListener,而在onTouchListeneronTouch方法返回的是true,这个时候onClick事件不走,因为这个时候不调用onTouchEvent方法,而系统调用onclick事件在onTouchEvent中捕获到up事件时,根据条件判断执行的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android触摸事件分发是指在屏幕上发生触摸事件时,Android系统将该事件分发给适当的视图处理触摸事件分发的过程涉及多个层级,包括Activity、ViewGroup和View。 当用户触摸屏幕时,Android系统首先将触摸事件发送给当前活动的Window。然后,Window将事件传递给顶级ViewGroup(通常是根布局),该ViewGroup负责协调子视图的事件处理。 在ViewGroup中,触摸事件会按照一定的规则进行分发。常见的分发方式有以下几种: 1. 捕获阶段(Capture Phase):从根布局向下遍历,让父级ViewGroup有机会拦截事件。可以通过重写`onInterceptTouchEvent()`方法来实现事件的拦截。 2. 目标阶段(Target Phase):如果没有被拦截,触摸事件将传递给目标View,即最终接收事件的视图。目标View将调用`onTouchEvent()`方法处理事件。 3. 冒泡阶段(Bubble Phase):如果目标View没有消耗事件事件将向上传递给父级ViewGroup,直到根布局。在这个阶段,可以通过返回值来控制是否继续向上传递。 除了上述的默认分发方式外,还可以通过重写`dispatchTouchEvent()`方法来自定义事件分发逻辑。通过调用`super.dispatchTouchEvent()`来保持默认行为,或者根据需求进行处理。 总结来说,Android触摸事件分发涉及捕获阶段、目标阶段和冒泡阶段,通过重写相关方法或自定义分发逻辑,可以实现对触摸事件处理和控制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值