Android事件分发机制(一)

Android事件分发

事件传递,实际上传递的是MotionEvent对象。

MotionEvent

该类的对象保存了事件的类型,触摸的坐标,产生的时间等信息

 

Android事件分发是从父view传递到子view的。其中的关键是dispatchtouchEvent、onInterceptTouchEvent和onTouchEvent方法,所以先简单介绍这三个方法。

 

dispatchTouchEvent

当发生触摸事件传递必定会调用这个方法,dispatchTouchEvent方法会把事件往目标子view传递。方法返回true则不再传递,该方法自己消费事件;返回false则不再向下传递,而是把事件传到父view的onTouchEvent方法;返回super.dispatchTouchEvent则调用自己的onInterceptTouchEvent;(本文默认dispatchTouchEvent方法返回true或false的情况下,方法内部将不在调用super.dispatchTouchEvent,否则事件传递流程将与本文介绍的不一致,因为super.dispatchTouchEvent方法内会继续处理事件的分发)

 

onInterceptTouchEvent

这个方法是ViewGroup特有的,普通View(如TextView、ImageView)是没有的。方法返回true表示当前ViewGroup对事件拦截,事件传到本身的onTouchEvent;返回false则放行,把事件传递给子View的dispatchTouchEvent;

 

onTouchEvent

这个事件处理的方法。方法返回true则事件不再传递,方法自己消费事件;返回false则把事件传到父view的onTouchEvent方法;返回super.onTouchEvent也会事件传到父view的onTouchEvent方法。该方法在View的dispatchTouchEvent方法内部调用。如果一个view设置了OnclickListener,就会在它的内部调用OnClick方法。

 

ACTION_DOWN事件

Android ACTION_DOWN事件的传递是从父View一层一层的通过dispatchTouchEven发方法往子View传递的,如果传递途中都不对事件处理,又会一层一层的从子view通过onTouchEvent方法传到父View。下图是ACTION_DOWM事件分发的一个流程。按照默认的流程,传递过程的每一个View都不消费事件,完整的流程就是Activity.dispatchTouchEvent -> ViewGroup.dispatchTouchEvent -> ViewGroup.onIntercepteTouchEvent -> View.dispatchTouchEvent -> View.onTouchEvent -> ViewGroup.onTouchEvent -> Activity.onTouchEvent。

 

 

ACTION_MOVE、ACTION_UP事件

ACTION_MOVE、ACTION_UP事件分发和ACTION_DOWM略有不同,这两个事件的分发流程受ACTION_DOWN事件的影响。在Android事件分发的过程中,如果一个View对ACTION_DOWN事件不做处理,那么这个view将不会再接收到ACTION_MOVE、ACTION_UP事件。如下图所示,ACTION_DOWM事件分发到最下面View,View并没有对事件做处理,而 ViewGroup B的onTouchEvent返回true表示对事件做了处理。那么后续的ACTION_MOVE、ACTION_UP事件将不会再传给最下面的View,而是直接通过ViewGroup B的dispatchTouchEvent方法传到了onTouchEvent方法(红线表示ACTION_MOVE、ACTION_UP事件,黑线表示ACTION_DOWN事件)。同时,也可以看到事件传递到ViewGroupB onTouchEvent方法就终止了,因为它返回true,已经消费了事件就不会再往上传递了。如果整个流程都不处理ACTION_DOWN事件,那么ACTION_MOVE和ACTION_UP只会从Activity.dispatchTouchEvent方法传递到Activity.onTouchEvent方法。

 

 

OnTouchListener和OnClickListener

view设置了OnTouchListener,那么事件传递给onTouchEvent之前,都会先调用onTouch()方法。如果onTouch返回true,则事件被消费,不再传递;返回false表示onTouch()不做处理,事件传递给onTouchEvent,然后继续传递下去。(onClick方法是在onTouchEvent内部调用的,所以这就是为什么onTouch返回true之后,onClick方法就不会被调用 )

view设置了OnClickListener,那么onTouchEvent方法就返回true,表示消费了事件。原因是在设置点击事件的时候view的clickable被设置为true,如果一个view的clickable为true,那么方法onTouchEvent就返回true(注意,有些控件clickable默认为true,如Button的clickable默认为true,TextView的clickable默认为false)。同理设置OnLongClickListener同样会导致onTouchEvent方法返回true。

所以这几个方法的调用顺序是onTouch -> onTouchEvent -> onClick

小结

事件分发的流程主要通过dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent方法处理,其中onInterceptTouchEvent方法只有ViewGroup才有。下篇博客将从源码分析事件分发机制。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值