View的事件分发机制详解

来源:互联网 发布:java并发编程面试题 编辑:程序博客网 时间:2024/06/03 17:38




 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的结构图如下所示:



 


以下是代码:



 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的事件分发机制进行了详细说明。
 




原创粉丝点击