天天看点

View的事件分发机制详解

View的事件分发机制详解
View的事件分发机制详解
View的事件分发机制详解

 View事件的分发机制请参考以上流程图的截图,现在进行以下文字说明。

 1、dispatchTouchEvent(Activity) -> dispatchTouchEvent (FatcherViewGroup) -> onInterceptTouchEvent(FatcherViewGroup) -> dispatchTouchEvent (    SonViewGroup) -> onInterceptTouchEvent(SonViewGroup) ..........

 以上是从Activity开始先进入dispatchTouchEvent如果返回true则后续不比再往下分发,如果dispatchTouchEvent返回false则进入onInterceptTouchEvent,如果为true本View拦截所有事件,不必继续往下继续分发;如果该值为false则继续往下分发。其中Activity中没有onInterceptTouchEvent所以不执行。

 2、如果dispatchTouchEvent为true或者onInterceptTouchEvent为true,则本View处理所有的分发事件,执行顺序如下:

    以FatcherViewGroup的onInterceptTouchEvent为例:

    dispatchTouchEvent(Activity,Action_Down) -> dispatchTouchEvent (FatcherViewGroup,Action_Down) -> onInterceptTouchEvent(FatcherViewGroup,Action_Down) -> onTouchEvent(FatcherViewGroup,Action_Down)-> dispatchTouchEvent(Activity,Action_Move) -> dispatchTouchEvent (FatcherViewGroup,Action_Move) -> onInterceptTouchEvent(FatcherViewGroup,Action_Move) -> onTouchEvent(FatcherViewGroup,Action_Move)-> ...... .... -> dispatchTouchEvent(Activity,Action_Up) -> dispatchTouchEvent (FatcherViewGroup,Action_Up) -> onInterceptTouchEvent(FatcherViewGroup,Action_Up) -> onTouchEvent(FatcherViewGroup,Action_Up)

    如果FatcherViewGroup中的 onTouchEvent返回为false并且FatcherViewGroup设置了OnClickListener(即是有了点击事件的监听)则在执行FatcherViewGroup的Action_Up之后OnTouchEvent后面追加如下:onTouchEvent(FatcherViewGroup,Action_Up) -> performClick (FatcherViewGroup,Action_Up)-> Click (FatcherViewGroup,Action_Up)。当然执行performClick返回为false才会执行click。

 以上已经完整的对View的分发事件进行了说明,现在写个DEMO进行测试

DEMO的结构图如下所示:

View的事件分发机制详解

以下是代码:

 a、touch_event_main.xml

 <?xml version="1.0" encoding="utf-8"?>

 <com.example.wangqiubo.myapplication.vieweventdispatch.FatherTouchEventView xmlns:android="http://schemas.android.com/apk/res/android"

  android:id="@+id/father_event"

  android:orientation="vertical" android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:gravity="center"

  android:background="#ff0000">

  <com.example.wangqiubo.myapplication.vieweventdispatch.SonTouchEventView

   android:id="@+id/son_touchevent"

   android:layout_width="600px"

   android:layout_height="1000px"

   android:orientation="horizontal"

   android:gravity="center"

   android:background="#00ff00">

   <com.example.wangqiubo.myapplication.vieweventdispatch.Son2SonTouchEventView

    android:layout_width="400px"

    android:layout_height="800px"

    android:gravity="center"

    android:background="#0000ff">

  </com.example.wangqiubo.myapplication.vieweventdispatch.Son2SonTouchEventView>

  </com.example.wangqiubo.myapplication.vieweventdispatch.SonTouchEventView>

 </com.example.wangqiubo.myapplication.vieweventdispatch.FatherTouchEventView>

 b、ViewEventActivity.java

 package com.example.wangqiubo.myapplication.vieweventdispatch;

 import android.app.Activity;

 import android.os.Bundle;

 import android.util.Log;

 import android.view.MotionEvent;

 import android.view.View;

 import com.example.wangqiubo.myapplication

.R;

 public class ViewEventActivity extends Activity implements View.OnClickListener{

  FatherTouchEventView fatherTouchEventView = null;

  SonTouchEventView sonTouchEventView = null;

  @Override

  public void onCreate(Bundle bundle){

   super.onCreate(bundle);

   setContentView(R.layout.touch_event_main);

   fatherTouchEventView = (FatherTouchEventView)findViewById(R.id.father_event);

   sonTouchEventView = (SonTouchEventView)findViewById(R.id.son_touchevent);

   fatherTouchEventView.setOnClickListener(this);

   sonTouchEventView.setOnClickListener(this);

  }

  @Override

  public boolean dispatchTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "Activity_dispatch_" + MotinEventUtil.getTouchEventName(event));

   return super.dispatchTouchEvent(event);

  }

  @Override

  public boolean onTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "Activity_touchEvent_" + MotinEventUtil.getTouchEventName(event));

   return super.onTouchEvent(event);

  }

  @Override

  public void onClick(View v) {

   Log.d("ViewMotinEvent: ", "Activity_onClick");

   if(v.getId() == R.id.father_event){

    Log.d("ViewMotinEvent: ", "Activity_Father_onClickListenler");

   }else if (v.getId() == R.id.son_touchevent){

    Log.d("ViewMotinEvent: ", "Activity_Son_onClickListenler");

   }

  }

 }

 c、FatherTouchEventView.java。

 package com.example.wangqiubo.myapplication.vieweventdispatch;

 import android.content.Context;

 import android.util.AttributeSet;

 import android.util.Log;

 import android.view.MotionEvent;

 import android.view.View;

 import android.widget.LinearLayout;

 public class FatherTouchEventView extends LinearLayout implements View.OnClickListener{

  public FatherTouchEventView(Context context) {

   super(context);

  }

  public FatherTouchEventView(Context context,  AttributeSet attrs) {

   super(context, attrs);

  }

  @Override

  public boolean dispatchTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "father_dispatch_" + MotinEventUtil.getTouchEventName(event));

 //        return false;

 //        return true;

   return super.dispatchTouchEvent(event);

  }

  @Override

  public boolean onInterceptTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "father_intercept_" + MotinEventUtil.getTouchEventName(event));

 //        return true;

 //        return false;

   return super.onInterceptTouchEvent(event);

  }

  @Override

  public boolean onTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "father_touch_" + MotinEventUtil.getTouchEventName(event));

 //        return false;

   return super.onTouchEvent(event);

  }

  @Override

  public boolean performClick() {

   Log.d("ViewMotinEvent: ", "father_performClick");

   return super.performClick();

 //        return true;//super.performClick();

  }

  @Override

  public void onClick(View v) {

   Log.d("ViewMotinEvent: ", "Father_onClick");

  }

 }

 d、SonTouchEventView.java。

 package com.example.wangqiubo.myapplication.vieweventdispatch;

 import android.content.Context;

 import android.support.annotation.Nullable;

 import android.util.AttributeSet;

 import android.util.Log;

 import android.view.MotionEvent;

 import android.view.View;

 import android.widget.LinearLayout;

 public class SonTouchEventView extends LinearLayout implements View.OnClickListener {

  public SonTouchEventView(Context context) {

   super(context);

  }

  public SonTouchEventView(Context context, @Nullable AttributeSet attrs) {

   super(context, attrs);

  }

  public SonTouchEventView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

   super(context, attrs, defStyleAttr);

  }

  @Override

  public boolean dispatchTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son_dispatch_" + MotinEventUtil.getTouchEventName(event));

 //        return true;

   return super.dispatchTouchEvent(event);

  }

  @Override

  public boolean onInterceptTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son_intercept_" + MotinEventUtil.getTouchEventName(event));

 //        return true;

   return super.onInterceptTouchEvent(event);

  }

  @Override

  public boolean onTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son_touch_" + MotinEventUtil.getTouchEventName(event));

   return super.onTouchEvent(event);

  }

  @Override

  public boolean performClick() {

   Log.d("ViewMotinEvent: ", "son_performClick_");

   return super.performClick();

  }

  @Override

  public void onClick(View v) {

   Log.d("ViewMotinEvent: ", "Son_onClick");

  }

 }

 e、Son2SonTouchEventView.java。

 package com.example.wangqiubo.myapplication.vieweventdispatch;

 import android.content.Context;

 import android.support.annotation.Nullable;

 import android.util.AttributeSet;

 import android.util.Log;

 import android.view.MotionEvent;

 import android.view.View;

 import android.widget.LinearLayout;

 public class Son2SonTouchEventView extends LinearLayout implements View.OnClickListener {

  public Son2SonTouchEventView(Context context) {

   super(context);

  }

  public Son2SonTouchEventView(Context context, @Nullable AttributeSet attrs) {

   super(context, attrs);

  }

  public Son2SonTouchEventView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

   super(context, attrs, defStyleAttr);

  }

  @Override

  public boolean dispatchTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son2son_dispatch_" + MotinEventUtil.getTouchEventName(event));

 //        return true;

   return super.dispatchTouchEvent(event);

  }

  @Override

  public boolean onInterceptTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son2son_intercept_" + MotinEventUtil.getTouchEventName(event));

   return super.onInterceptTouchEvent(event);

  }

  @Override

  public boolean onTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son2son_touch_" + MotinEventUtil.getTouchEventName(event));

   return super.onTouchEvent(event);

  }

  @Override

  public boolean performClick() {

   Log.d("ViewMotinEvent: ", "son2son_performClick_");

 //        return  true;

   return super.performClick();

  }

  @Override

  public void onClick(View v) {

   Log.d("ViewMotinEvent: ", "Son2Son_onClick");

  }

 }

 请查看touch_event_main.xml,知道Son2SonTouchEventView 是 SonTouchEventView子节点,而SonTouchEventView是FatherTouchEventView子节点。

 1、我们现在修改SonTouchEventView中的dispatchTouchEvent代码,修改如下:

  @Override

  public boolean dispatchTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son_dispatch_" + MotinEventUtil.getTouchEventName(event));

         return true;

 //  return super.dispatchTouchEvent(event);

  }

  即是dispatchTouchEvent返回true拦截事件,打印出的日志如下:

  05-24 02:27:29.454 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_domn

  05-24 02:27:29.454 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_domn

  05-24 02:27:29.454 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_domn

  05-24 02:27:29.454 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_domn

  05-24 02:27:29.757 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

  05-24 02:27:29.757 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

  05-24 02:27:29.757 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_move

  05-24 02:27:29.757 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_move

  05-24 02:27:29.774 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

  05-24 02:27:29.774 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

  05-24 02:27:29.774 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_move

  05-24 02:27:29.774 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_move

  .

  .

  .

  05-24 02:27:30.189 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_up

  05-24 02:27:30.190 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_up

  05-24 02:27:30.190 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_up

  05-24 02:27:30.190 2495-2495/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_up

  因为Son2SonTouchEventView的dispatchTouchEvent拦截事件,所以终点在该VIEW的dispatchTouchEvent,后续的事件及其子节点的分发不再执行。

  需要注意,每次的事件分发都是从顶级结点开始也就是Activity开始分发,分发出去,后续子View来决定是否拦截(是否拦截根据业务本身来决定)。

 2、如果SonTouchEventView中的onInterceptTouchEvent代码,修改如下:

  @Override

  public boolean onInterceptTouchEvent(MotionEvent event){

   Log.d("ViewMotinEvent: ", "son_intercept_" + MotinEventUtil.getTouchEventName(event));

         return true;

 //  return super.onInterceptTouchEvent(event);

  }

  即是onInterceptTouchEvent返回true拦截事件,打印出的日志如下:

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_domn

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_domn

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_domn

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_domn

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_intercept_action_domn

  05-24 02:39:54.977 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_domn

  05-24 02:39:55.308 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

  05-24 02:39:55.308 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

  05-24 02:39:55.309 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_move

  05-24 02:39:55.309 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_move

  05-24 02:39:55.309 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_move

  .

  .

  .

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_up

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_up

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_up

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_up

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_up

  05-24 02:39:55.662 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_performClick

  05-24 02:39:55.665 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_onClick

  05-24 02:39:55.665 15550-15550/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_Son_onClickListenler

  Son2SonTouchEventView的onInterceptTouchEvent拦截事件,则需要执行Son2SonTouchEventView中的onTouchEvent方法,进过无数个move,当执行Aciton_Up之后,因为onTouchEvent的返回值为false则事件需要继续传递,因为Son2SonTouchEventView设置了点击事件的监听,因此首选执行到performClick,因为performClick也返回为false,则继续往下执行进入ViewEventActivity的onClick,执行ViewEventActivity中设置的onClickListenler。(注意并没有执行Son2SonTouchEventView的click是因为click是设置的Activity,Activity继承了onClickListenler,本身performClick内部代码中会执行click)。

 3、如果SonTouchEventView的代码不进行修改,按照以上文件进行执行结果会怎样呢?以下是输出的日志。

 05-24 02:51:22.453 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_domn

 05-24 02:51:22.453 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_domn

 05-24 02:51:22.453 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_intercept_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_dispatch_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_intercept_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_touch_action_domn

 05-24 02:51:22.454 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_domn

 05-24 02:51:22.858 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

 05-24 02:51:22.858 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_move

 05-24 02:51:22.859 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_move

 05-24 02:51:22.859 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_move

 .

 .

 .

 05-24 02:51:23.000 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_up

 05-24 02:51:23.000 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_up

 05-24 02:51:23.000 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_up

 05-24 02:51:23.001 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_up

 05-24 02:51:23.001 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_up

 05-24 02:51:23.001 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_performClick_

 05-24 02:51:23.009 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_onClick

 05-24 02:51:23.009 25477-25477/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_Son_onClickListenler

 本输出日志有没注意到一个问题,在输出son2son_touch_action_domn之后,为什么之后没有执行Son2son_touch_action_move 和 Son2son_touch_action_up,而是执行的他的父亲结点

 son_touch_action_move和son_touch_action_up,然后执行的其父亲结点的son_performClick。

 要解决这问题,不妨,我们修改ViewEventActivity的代码如下:

 注释掉这行代码 ://sonTouchEventView.setOnClickListener(this);

 输入日志如下:

 05-24 03:01:07.740 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_domn

 05-24 03:01:07.740 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_domn

 05-24 03:01:07.740 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_domn

 05-24 03:01:07.740 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_domn

 05-24 03:01:07.740 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_intercept_action_domn

 05-24 03:01:07.741 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_dispatch_action_domn

 05-24 03:01:07.741 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_intercept_action_domn

 05-24 03:01:07.741 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_touch_action_domn

 05-24 03:01:07.741 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_domn

 05-24 03:01:07.741 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_domn

 05-24 03:01:08.041 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:01:08.041 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

 05-24 03:01:08.041 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_move

 05-24 03:01:08.059 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:01:08.060 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

 05-24 03:01:08.060 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_move

 05-24 03:01:08.078 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:01:08.078 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_move

 05-24 03:01:08.078 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_move

 .

 .

 .

 05-24 03:01:08.385 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_up

 05-24 03:01:08.385 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_up

 05-24 03:01:08.385 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_up

 05-24 03:01:08.385 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_performClick

 05-24 03:01:08.388 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_onClick

 05-24 03:01:08.388 549-549/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_Father_onClickListenler

 通过以上日志,我们发现,这次并没有执行Son2son_touch_action_move 和 Son2son_touch_action_up ,并且没有执行其直接父亲的son_touch_action_move和son_touch_action_up,而是执行了其上上层父亲的的father_touch_action_move 和 father_touch_action_up及其 father_performClick

 综合以上2个输入日志,得出的结论就是因为Son2SonTouchEventView没有设置Click的监听,并且其onTouchEvent返回为false,onTouchEvent 返回false则往上传一层,让其父亲处理,当其直接父亲SonTouchEventView设置了click事件监听时,自然而然进入了SonTouchEventView的performClick,执行完毕后回到了其click事件(Activity中)中,当SonTouchEventView没有设置click事件监听时,则事件继续往上一层传递,则传给了他的父亲FatherTouchEventView。

 因此后续事件均由设置了click监听的View执行。因为SonTouchEventView 和 FatherTouchEventView 设置的OnClickListener是 ViewEventActivity,因此相对于performClick不处理事件的话,后续执行的是设置的OnClickListener,因此执行了Activity的click。

 我们将代码修改为如下:

 屏蔽掉ViewEventActivity中的以下两行:       

 //fatherTouchEventView.setOnClickListener(this);

    //sonTouchEventView.setOnClickListener(this);

 则事件分发,因为Son2SonTouchEventView、Son2SonTouchEventView、FatherTouchEventView都没有处理,则最后就交给了ViewEventActivity处理。

 05-24 03:23:59.905 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_dispatch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_intercept_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_dispatch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_intercept_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_dispatch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_intercept_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son2son_touch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: son_touch_action_domn

 05-24 03:23:59.906 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: father_touch_action_domn

 05-24 03:23:59.907 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_domn

 05-24 03:24:00.145 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.145 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.159 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.159 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.175 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.176 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.190 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.190 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.207 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.208 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.224 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.224 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.241 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.241 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.257 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_move

 05-24 03:24:00.257 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_move

 05-24 03:24:00.323 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_dispatch_action_up

 05-24 03:24:00.323 21071-21071/com.example.wangqiubo.myapplication D/ViewMotinEvent:: Activity_touchEvent_action_up

 以上通过流程图了代码,对VIEW的事件分发机制进行了详细说明。