事件拦截机制分析

    Android为触摸事件封装了一个类-------MotionEvent.如果重写onTouchEvent()方法,你就会发现该方法的参数就是这样一个MotionEvent。其实,只要是重写触摸相关的方法,参数一般都含有MotionEvent,可见它的重要性。

    在MotionEvent里面封装了不少好东西,比如触摸点的坐标,可以通过event.getX()方法,和event.getRawX()方法获取出坐标点;再比如获取点击事件类型,可以通过不同的Action(如 MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE)来进行区分,并实现不同的逻辑。

   如此看来,触摸事件还是比较简单的,其实就是一个动作类型加坐标而已。但是我们知道,Android的View结构是树形结构,也就是说,View可以放在ViewGroup里面,通过不同组合来实现不同的样式。那么问题来了,View放在一个ViewGroup里面,这个ViewGroup又放在另一个ViewGroup里面,甚至还有可能继续嵌套,一层层叠起来。可我们的触摸事件就一个,到底该分给谁呢?同一个事件,子View和父ViewGroup都有可能想要进行处理。因此,这就产生了“事件拦截”这个霸气的称呼。

    首先,想象一下生活中非常常见的场景:假如你所在的公司,有一个总经理,级别最高;他下面有一个部长,级别次之;最底层,就是干活的你,没有级别。而你好不容易干完活了,你就把任务交给部长,部长觉得任务完成的不错,于是就签了他的名字交给总经理,总经理看了也觉得不错,就也签了名字交给董事会。我们Android中的事件拦截机制也差不多是这个模式。

    

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.myapplication.MainActivity">

 <com.example.administrator.myapplication.MyViewGroupA
     android:layout_width="match_parent"
     android:layout_height="match_parent">


     <com.example.administrator.myapplication.MyViewGroupB
         android:layout_width="match_parent"
         android:layout_height="match_parent">

         <com.example.administrator.myapplication.MyView
             android:layout_width="match_parent"
             android:layout_height="match_parent" />


     </com.example.administrator.myapplication.MyViewGroupB>

 </com.example.administrator.myapplication.MyViewGroupA>

</android.support.constraint.ConstraintLayout>

我们来点击一下,看一下LOG

  

从上面的log我们知道了事件的处理顺序。

   在事件的传递过程中,我们只关心onInterceptTouchEvent()方法,而dispatchTouchEvent()方法虽然是事件分发的第一步,但一般情况下,我们不太会改写这个方法,所以暂时不管这个方法。

  下面我们稍微改动一下,假设总经理(MyViewGroupA)发现这个任务太简单了,觉得自己完成就可以了,完全没有必要再找下属。因此事件就被总经理(MyViewGroupA)使用onInterceptTouchEvent()方法把事件给拦截了,即让MyViewGroupA的onInterceptTouchEvent()方法返回True,我们再来看下log

下面,我们让部长也来当一次好人,在onInterceptTouchEvent中返回true。

可以看到,这次部长当了好人,MyView就不用干活了。

   最看是讲了,当你处理完任务后会向上级报告,需要上级确认,所以你的事件处理返回False。那么你突然有一天受不了老板的压迫了,罢工不干了,那么你的任务就没人做了,也就不用报告上级了,所以直接返回true。再来看看log

可以看见,事件的传递跟以前一样,但是事件的处理,到你View这里就结束了,因为你返回true,标识不用向上级汇报了。

 但是也可是是部长看了你的报告觉得太丢人了,不传给上级了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值