首页 > 代码库 > 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 触摸事件 点击事件的分发机制 详解二