现在我们来看看 事件分发的流程。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 stub 14 } 15 16 public MyLayout(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 public boolean onInterceptTouchEvent(MotionEvent ev) { 23 // TODO Auto-generated method stub 24 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 @Override 39 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 stub 14 } 15 16 public MyTextView(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 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 stub 14 } 15 16 public MyTextView(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 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 stub 14 } 15 16 public MyLayout(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 public boolean onInterceptTouchEvent(MotionEvent ev) { 23 // TODO Auto-generated method stub 24 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 @Override 39 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 stub 14 } 15 16 public MyLayout(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 public boolean onInterceptTouchEvent(MotionEvent ev) { 23 // TODO Auto-generated method stub 24 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 @Override 39 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。