(本文基于android-2.3.3_r1代码研究)
onTouchEvent
onTouchEvent是View类提供的方法,其说明如下:
实现onTouchEvent方法可以处理View的触屏事件,返回true表明事件已被处理,不需要继续派发,否则返回false。
Demo
如下自定义View布局文件
在MyView上按下触屏并滑动
1. MyView中onTouchEvent返回false
E/MyView﹕ onTouchEvent:false action:ACTION_DOWN
可以看到onTouchEvent返回false时,只会收到第一次的down事件,后续的move、up事件都不再派发给MyView
2. MyView中onTouchEvent返回true
E/MyView﹕ onTouchEvent:true action:ACTION_DOWN
E/MyView﹕ onTouchEvent:true action:ACTION_MOVE
E/MyView﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyView﹕ onTouchEvent:true action:ACTION_MOVE
E/MyView﹕ onTouchEvent:true action:ACTION_UP
可以看到onTouchEvent返回true时,所有的down、move、up事件都会派发给MyView处理
###总结
-
onTouchEvent返回true,父ViewGroup派发过来的touch事件已被该View消费,不会再向上传递给父ViewGroup;后续的touch事件都将继续传递给View
-
onTouchEvent返回false,表明View并不消费父ViewGroup传递来的down事件,而是向上传递给父ViewGroup来处理;后续的move、up等事件将不再传递给View,直接由父ViewGroup处理掉
onInterceptTouchEvent
onInterceptTouchEvent()方法是ViewGoup中的方法,其注释如下:
实现onInterceptTouchEvent方法可以用来拦截父ViewGroup传递下来的所有触屏事件,可以将所有触屏事件交由此ViewGroup自身的onTouchEvent来处理,也可以继续传递给其子View来处理。
onInterceptTouchEvent方法对触屏事件的拦截处理需要和onTouchEvent方法配合使用。
-
down事件首先传递到onInterceptTouchEvent方法中
-
onInterceptTouchEvent返回false表示将down事件交由子View来处理;若某一层子View的onTouchEvent返回了true,后续的move、up等事件都将先传递到ViewGroup的onInterceptTouchEvent的方法,并继续层层传递下去,交由子View处理;若子View的onTouchEvent都返回了false,则down事件将交由该ViewGroup的onTouchEvent来处理;如果ViewGroup的onTouchEvent返回false,down传递给父ViewGroup,后续事件不再传递给该ViewGroup;如果ViewGroup的onTouchEvent返回true,后续事件不再经过该ViewGroup的onInterceptTouchEvent方法,直接传递给onTouchEvent方法处理
-
onInterceptTouchEvent返回ture,down事件将转交该ViewGroup的onTouchEvent来处理;若onTouchEvent返回true,后续事件将不再经过该ViewGroup的onInterceptTouchEvent方法,直接交由该ViewGroup的onTouchEvent方法处理;若onTouchEvent方法返回false,后续事件都将交由父ViewGroup处理,不再经过该ViewGroup的onInterceptTouchEvent方法和onTouchEvent方法
一. 没有子View的ViewGroup
1. MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回false
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
由于没有子View,down传递给MyLayout的onTouchEvent方法来处理;
onTouchEvent返回了false,表示MyLayout不处理touch事件,down事件传递给父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
2. MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回true
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
由于没有子View,down传递给MyLayout的onTouchEvent方法来处理;
onTouchEvent返回true,down事件不再向上传递,后续move、up等事件不再传递给onInterceptTouchEvent方法,直接交由onTouchEvent处理
3. MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回false
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down事件直接传递给MyLayout的onTouchEvent方法来处理;
onTouchEvent返回了false,表示MyLayout不处理touch事件,down事件传递给父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
4. MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回true
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down事件直接传递给MyLayout的onTouchEvent方法来处理;
onTouchEvent返回true,down事件不再向上传递,后续move、up等事件不再传递给onInterceptTouchEvent方法,直接交由onTouchEvent处理
二. ViewGroup嵌套View
布局如下:
1.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回false
MyView的onTouchEvent返回false
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyView﹕ onTouchEvent:false action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyView的onTouchEvent方法来处理;
MyView的onTouchEvent返回了false,表示MyView不处理down事件,down事件传递给MyLayout的onTouchEvent方法处理;
MyLayout的onTouchEvent返回false,down事件继续传递给其父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
2.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回true/false
MyView的onTouchEvent返回true
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyView﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyView﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyView﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_UP
E/MyView﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyView的onTouchEvent方法来处理;
MyView的onTouchEvent返回了true,表示MyView消费了down事件,不再向上传递,MyLayout的onTouchEvent的返回值此时不起作用
后续的move、up等事件继续由MyLayout的onInterceptTouchEvent方法传递到MyView的onTouchEvent方法进行处理
3.
MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回false
MyView的onTouchEvent返回true/false
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down直接传递给MyLayout的onTouchEvent方法来处理;MyView的onTouchEvent方法的返回值不起作用
MyLayout的onTouchEvent返回false,down事件继续传递给其父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
4.
MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回true
MyView的onTouchEvent返回true/false
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down直接传递给MyLayout的onTouchEvent方法来处理;MyView的onTouchEvent方法的返回值不起作用
MyLayout的onTouchEvent返回true,down事件由MyLayout消费,不再向上传递;
后续的move、up等事件将不再传递给MyLayout的onInterceptTouchEvent方法,而是直接传递给MyLayout的onTouchEvent方法来处理
二. ViewGroup嵌套ViewGroup
布局如下:
1.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回false
MyLayout2的onInterceptTouchEvent返回false,onTouchEvent返回false
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onTouchEvent:false action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyLayout2的onInterceptTouchEvent方法处理;
由于MyLayout2没有子View,down事件传递给MyLayout2的onTouchEvent方法来处理;
MyLayout2的onTouchEvent返回了false,表示MyLayout2不处理down事件,down事件传递给MyLayout的onTouchEvent方法处理;
MyLayout的onTouchEvent返回false,down事件继续传递给其父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
2.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回true/false
MyLayout2的onInterceptTouchEvent返回false,的onTouchEvent返回true
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
...
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_UP
E/MyLayout2﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyLayout2的onInterceptTouchEvent方法处理;
由于MyLayout2没有子View,down事件传递给MyLayout2的onTouchEvent方法来处理;
MyLayout2的onTouchEvent返回了true,表示MyLayout2消费了down事件,不再向上传递,MyLayout的onTouchEvent的返回值此时不起作用
后续的move、up等事件继续由MyLayout的onInterceptTouchEvent方法传递到MyLayout2,不再经过MyLayout2的onInterceptTouchEvent方法,直接传递给MyLayout2的onTouchEvent方法进行处理
3.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回false
MyLayout2的onInterceptTouchEvent返回true,onTouchEvent返回false
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout2﹕ onTouchEvent:false action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyLayout2的onInterceptTouchEvent方法处理;
MyLayout2的onInterceptTouchEvent方法返回true,down事件直接传递给MyLayout2的onTouchEvent方法来处理;
MyLayout2的onTouchEvent返回了false,表示MyLayout2不处理down事件,down事件传递给MyLayout的onTouchEvent方法处理;
MyLayout的onTouchEvent返回false,down事件继续传递给其父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
4.
MyLayout的onInterceptTouchEvent返回false,onTouchEvent返回true/false
MyLayout2的onInterceptTouchEvent返回true,onTouchEvent返回true
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_DOWN
E/MyLayout2﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout2﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_MOVE
E/MyLayout2﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onInterceptTouchEvent:false action:ACTION_UP
E/MyLayout2﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回false,down传递给MyLayout2的onInterceptTouchEvent方法处理;
MyLayout2的onInterceptTouchEvent方法返回true,down事件直接传递给MyLayout2的onTouchEvent方法来处理;
MyLayout2的onTouchEvent返回了true,表示MyLayout2消费了down事件,不再向上传递,MyLayout的onTouchEvent的返回值此时不起作用
后续的move、up等事件继续由MyLayout的onInterceptTouchEvent方法传递到MyLayout2,不再经过MyLayout2的onInterceptTouchEvent方法,直接传递给MyLayout2的onTouchEvent方法进行处理
5.
MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回false
MyLayout2的onInterceptTouchEvent返回true/false,onTouchEvent返回true/false
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:false action:ACTION_DOWN
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down直接传递给MyLayout的onTouchEvent方法处理,不传递给MyLayout2;MyLayout2的onInterceptTouchEvent方法和onTouchEvent方法返回值不影响事件传递
MyLayout的onTouchEvent返回false,down事件继续传递给其父ViewGroup的onTouchEvent方法处理,后续的move、up等事件都不再传递给MyLayout,直接交由父ViewGroup处理。
6.
MyLayout的onInterceptTouchEvent返回true,onTouchEvent返回true
MyLayout2的onInterceptTouchEvent返回true/false,onTouchEvent返回true/false
E/MyLayout﹕ onInterceptTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_DOWN
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
......
E/MyLayout﹕ onTouchEvent:true action:ACTION_MOVE
E/MyLayout﹕ onTouchEvent:true action:ACTION_UP
MyLayout的down事件首先传递到onInterceptTouchEvent方法;
onInterceptTouchEvent方法返回true,down直接传递给MyLayout的onTouchEvent方法处理,不传递给MyLayout2;MyLayout2的onInterceptTouchEvent方法和onTouchEvent方法返回值不影响事件传递
MyLayout的onTouchEvent返回了true,表示MyLayout消费了down事件,不再向上传递
后续的move、up等事件直接由父ViewGroup传递给MyLayout的onTouchEvent方法处理,不在经过MyLayout的onInterceptTouchEvent方法。
总结
-
touch事件在onInterceptTouchEvent方法中的传递由父ViewGroup到子ViewGroup,在onTouchEvent方法中传递则相反。
-
onInterceptTouchEvent方法和onTouchEvent方法的返回值为true都代表消费了事件,反之则为false
-
onInterceptTouchEvent消费事件表示将事件直接传递给ViewGroup自身的onTouchEvent事件,后续事件不再经过onInterceptTouchEvent方法;不消费事件则表示将事件传递给子View处理
-
onTouchEvent消费事件表示不再向上传递,后续事件继续传递给该View的onTouchEvent方法;不消费事件则表示将事件传递给父ViewGroup,后续事件不再传递给该View(该View是ViewGroup时onInterceptTouchEvent方法也不再收到后续事件)
Demo代码
demo代码可以在我的github上下载:Android触屏事件传递演示Demo
MyView、MyLayout、MyLayout2关键代码
相关文章
Android Touch事件传递机制(二) – OnTouchListener & OnClickListener & OnLongClickListener
Android Touch事件传递机制(三) – Touch事件分发(dispatchTouchEvent)
Android Touch事件传递机制(四) – Touch事件处理(onTouchEvent)