首页 > 代码库 > Android 触摸事件 点击事件的分发机制 详解二

Android 触摸事件 点击事件的分发机制 详解二

现在我们来看看 事件分发的流程。view group 怎么传递给view的。

首先自定义一个layout

 1 package com.example.testtouch; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.MotionEvent; 7 import android.widget.LinearLayout; 8  9 public class MyLayout extends LinearLayout {10 11     public MyLayout(Context context) {12         super(context);13         // TODO Auto-generated constructor stub14     }15 16     public MyLayout(Context context, AttributeSet attrs) {17         super(context, attrs);18         // TODO Auto-generated constructor stub19     }20 21     @Override22     public boolean onInterceptTouchEvent(MotionEvent ev) {23         // TODO Auto-generated method stub24 25         if (ev.getAction() == MotionEvent.ACTION_DOWN) {26             Log.v("test", "MyLayout onInterceptTouchEvent==DOWN");27         }28         if (ev.getAction() == MotionEvent.ACTION_UP) {29             Log.v("test", "MyLayout onInterceptTouchEvent==UP");30         }31         Log.v("test",32                 "MyLayout onInterceptTouchEvent 默认值=="33                         + super.onInterceptTouchEvent(ev));34 35         return super.onInterceptTouchEvent(ev);36     }37 38     @Override39     public boolean onTouchEvent(MotionEvent event) {40         if (event.getAction() == MotionEvent.ACTION_DOWN) {41             Log.v("test", "MyLayout onTouchEvent==DOWN");42         }43         if (event.getAction() == MotionEvent.ACTION_UP) {44             Log.v("test", "MyLayout onTouchEvent==UP");45         }46         Log.v("test", "MyLayout onTouchEvent 默认值==" + super.onTouchEvent(event));47         return super.onTouchEvent(event);48     }49 50 }

然后定义一个view

 1 package com.example.testtouch; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.MotionEvent; 7 import android.widget.TextView; 8  9 public class MyTextView extends TextView {10 11     public MyTextView(Context context) {12         super(context);13         // TODO Auto-generated constructor stub14     }15 16     public MyTextView(Context context, AttributeSet attrs) {17         super(context, attrs);18         // TODO Auto-generated constructor stub19     }20 21     @Override22     public boolean onTouchEvent(MotionEvent event) {23         if (event.getAction() == MotionEvent.ACTION_DOWN) {24             Log.v("test", "MyTextView onTouchEvent down事件");25         }26         if (event.getAction() == MotionEvent.ACTION_UP) {27             Log.v("test", "MyTextView onTouchEvent up 事件");28         }29 30         Log.v("test",31                 "MyTextView onTouchEvent==默认值==" + super.onTouchEvent(event));32         return super.onTouchEvent(event);33     }34 35 }

然后 我们来run 一下 这个界面。

并且点击一下 这个自定义的view 看看会发生什么。

 

10-31 08:53:44.620: V/test(7702): MyLayout onInterceptTouchEvent==DOWN
10-31 08:53:44.649: V/test(7702): MyLayout onInterceptTouchEvent 默认值==false
10-31 08:53:44.649: V/test(7702): MyTextView onTouchEvent down事件
10-31 08:53:44.649: V/test(7702): MyTextView onTouchEvent==默认值==false
10-31 08:53:44.649: V/test(7702): MyLayout onTouchEvent==DOWN
10-31 08:53:44.649: V/test(7702): MyLayout onTouchEvent 默认值==false

 

可以看出来 我们点击这个view的时候  是上层的layout先捕捉到了这个事件。 并且layout的 onInterceptTouchEvent 返回值 默认的是false。

然后把这个点击事件 传递给了 子空间 也就是这个view。 这个子view 也补获到了这个事件。并且子view的事件 捕捉到了以后 又抛给了 layout的ontouchevent 这个函数。

从而 layout的onTouchEvent也捕获到了这个action事件。

当然有人要问 一个点击事件 有down肯定有up,哪up事件 怎么没捕获到? 正如前面一篇博客讲的,onTouchEvent  这个函数。对于aciton down事件来说 如果返回false

后面的事件都捕获不到了。

我们可以验证一下  把 mytextview的 onTouchEvent返回值改写成固定的true。

看看会发生什么。

 1 package com.example.testtouch; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.MotionEvent; 7 import android.widget.TextView; 8  9 public class MyTextView extends TextView {10 11     public MyTextView(Context context) {12         super(context);13         // TODO Auto-generated constructor stub14     }15 16     public MyTextView(Context context, AttributeSet attrs) {17         super(context, attrs);18         // TODO Auto-generated constructor stub19     }20 21     @Override22     public boolean onTouchEvent(MotionEvent event) {23         if (event.getAction() == MotionEvent.ACTION_DOWN) {24             Log.v("test", "MyTextView onTouchEvent down事件");25         }26         if (event.getAction() == MotionEvent.ACTION_UP) {27             Log.v("test", "MyTextView onTouchEvent up 事件");28         }29 30         Log.v("test",31                 "MyTextView onTouchEvent==默认值==" + super.onTouchEvent(event));32         return true;33     }34 35 }

10-31 08:59:35.489: V/test(8740): MyLayout onInterceptTouchEvent==DOWN
10-31 08:59:35.489: V/test(8740): MyLayout onInterceptTouchEvent 默认值==false
10-31 08:59:35.489: V/test(8740): MyTextView onTouchEvent down事件
10-31 08:59:35.489: V/test(8740): MyTextView onTouchEvent==默认值==false
10-31 08:59:35.579: V/test(8740): MyLayout onInterceptTouchEvent==UP
10-31 08:59:35.579: V/test(8740): MyLayout onInterceptTouchEvent 默认值==false
10-31 08:59:35.579: V/test(8740): MyTextView onTouchEvent up 事件
10-31 08:59:35.579: V/test(8740): MyTextView onTouchEvent==默认值==false

 

可以看出来 对于 mytextview 来说 他的 up事件 也捕获到了 但是layout的 onTouchEvent 并没有捕获到up事件,甚至他的onTouchEvent都没有执行!!!!!!!

 

然后我们再把mylayout的onInterceptTouchEvent 的返回值改写成true 看看会有什么结果

 1 package com.example.testtouch; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.MotionEvent; 7 import android.widget.LinearLayout; 8  9 public class MyLayout extends LinearLayout {10 11     public MyLayout(Context context) {12         super(context);13         // TODO Auto-generated constructor stub14     }15 16     public MyLayout(Context context, AttributeSet attrs) {17         super(context, attrs);18         // TODO Auto-generated constructor stub19     }20 21     @Override22     public boolean onInterceptTouchEvent(MotionEvent ev) {23         // TODO Auto-generated method stub24 25         if (ev.getAction() == MotionEvent.ACTION_DOWN) {26             Log.v("test", "MyLayout onInterceptTouchEvent==DOWN");27         }28         if (ev.getAction() == MotionEvent.ACTION_UP) {29             Log.v("test", "MyLayout onInterceptTouchEvent==UP");30         }31         Log.v("test",32                 "MyLayout onInterceptTouchEvent 默认值=="33                         + super.onInterceptTouchEvent(ev));34 35         return true;36     }37 38     @Override39     public boolean onTouchEvent(MotionEvent event) {40         if (event.getAction() == MotionEvent.ACTION_DOWN) {41             Log.v("test", "MyLayout onTouchEvent==DOWN");42         }43         if (event.getAction() == MotionEvent.ACTION_UP) {44             Log.v("test", "MyLayout onTouchEvent==UP");45         }46         Log.v("test", "MyLayout onTouchEvent 默认值==" + super.onTouchEvent(event));47         return super.onTouchEvent(event);48     }49 50 }

10-31 09:06:20.649: V/test(9635): MyLayout onInterceptTouchEvent==DOWN
10-31 09:06:20.659: V/test(9635): MyLayout onInterceptTouchEvent 默认值==false
10-31 09:06:20.659: V/test(9635): MyLayout onTouchEvent==DOWN
10-31 09:06:20.659: V/test(9635): MyLayout onTouchEvent 默认值==false

发现 子view mytextview的事件根本捕获不到了!!!!!!!!!!!!被拦截在layout这一层了。

 

把layout的ontouchevent 改写成true 看看是否能捕获到up事件。

 

 1 package com.example.testtouch; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.MotionEvent; 7 import android.widget.LinearLayout; 8  9 public class MyLayout extends LinearLayout {10 11     public MyLayout(Context context) {12         super(context);13         // TODO Auto-generated constructor stub14     }15 16     public MyLayout(Context context, AttributeSet attrs) {17         super(context, attrs);18         // TODO Auto-generated constructor stub19     }20 21     @Override22     public boolean onInterceptTouchEvent(MotionEvent ev) {23         // TODO Auto-generated method stub24 25         if (ev.getAction() == MotionEvent.ACTION_DOWN) {26             Log.v("test", "MyLayout onInterceptTouchEvent==DOWN");27         }28         if (ev.getAction() == MotionEvent.ACTION_UP) {29             Log.v("test", "MyLayout onInterceptTouchEvent==UP");30         }31         Log.v("test",32                 "MyLayout onInterceptTouchEvent 默认值=="33                         + super.onInterceptTouchEvent(ev));34 35         return true;36     }37 38     @Override39     public boolean onTouchEvent(MotionEvent event) {40         if (event.getAction() == MotionEvent.ACTION_DOWN) {41             Log.v("test", "MyLayout onTouchEvent==DOWN");42         }43         if (event.getAction() == MotionEvent.ACTION_UP) {44             Log.v("test", "MyLayout onTouchEvent==UP");45         }46         Log.v("test", "MyLayout onTouchEvent 默认值==" + super.onTouchEvent(event));47         return true;48     }49 50 }

 

 

结果发现是可以捕获到的

 

10-31 09:07:56.620: V/test(9913): MyLayout onInterceptTouchEvent==DOWN
10-31 09:07:56.620: V/test(9913): MyLayout onInterceptTouchEvent 默认值==false
10-31 09:07:56.620: V/test(9913): MyLayout onTouchEvent==DOWN
10-31 09:07:56.620: V/test(9913): MyLayout onTouchEvent 默认值==false
10-31 09:07:56.712: V/test(9913): MyLayout onTouchEvent==UP
10-31 09:07:56.712: V/test(9913): MyLayout onTouchEvent 默认值==false

 

ViewGroup里的onInterceptTouchEvent默认值是false这样才能把事件传给View里的onTouchEvent.如果返回true 那上层layout就会拦截touch事件

ViewGroup里的onTouchEvent默认值是false。

 

 

Android 触摸事件 点击事件的分发机制 详解二