Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

时间:2024-05-31 09:01:38

【转】http://blog.****.net/guitk/article/details/7057155

onInterceptTouchEvent用于改变事件的传递方向。决定传递方向的是返回值,返回为false时事件会传递给子控件,返回值为true时事件会传递给当前控件的onTouchEvent(),这就是所谓的Intercept(拦截)。

[tisa ps:正确的使用方法是,在此方法内仅判断事件是否需要拦截,然后返回。即便需要拦截也应该直接返回true,然后由onTouchEvent方法进行处理。]

    onTouchEvent用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。尤其对于ACTION_DOWN事件,返回true,表示我想要处理后续事件;返回false,表示不关心此事件,并返回由父类进行处理。

    可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

在没有重写onInterceptTouchEvent()和onTouchEvent()的情况下(他们的返回值都是false), 对上面这个布局,MotionEvent事件的传递顺序如下:

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

当某个控件的onInterceptTouchEvent()返回值为true时,就会发生截断,事件被传到当前控件的onTouchEvent()。如我们将LayoutView2的onInterceptTouchEvent()返回值为true,则传递流程变成:

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

 如果我们同时将LayoutView2的onInterceptTouchEvent()和onTouchEvent()设置成true,那么LayoutView2将消费被传递的事件,同时后续事件(如跟着ACTION_DOWN的ACTION_MOVE或者ACTION_UP)会直接传给LayoutView2的onTouchEvent(),不传给其他任何控件的任何函数。同时传递给子空间一个ACTION_CANCEL事件。传递流程变成(图中没有画出ACTION_CANCEL事件):

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解         Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

[tisa ps:总体来看, onInterceptTouchEvent是自rootview向下传递, onTouchEvent正好相反。]

 

【转】http://blog.****.net/cyp331203/article/details/41039635

 

Android中触摸事件传递过程中最重要的是dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()方法。这个是困扰初学者的问题之一,我开始也是。这里记录一下dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()的处理过程,以供记忆。

 

    dispatchTouchEvent是处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行

super.dispatchTouchEvent(ev),事件向下分发。

    onInterceptTouchEvent是ViewGroup提供的方法,默认返回false,返回true表示拦截。

    onTouchEvent是View中提供的方法,ViewGroup也有这个方法,view中不提供onInterceptTouchEvent。view中默认返回true,表示消费了这个事件。

 

View里,有两个回调函数 :

 

[java] view plaincopyAndroid中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解
 
  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onTouchEvent(MotionEvent ev);   

 

 

ViewGroup里,有三个回调函数 :

 

[java] view plaincopyAndroid中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解
 
  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onInterceptTouchEvent(MotionEvent ev);    
  3. public boolean onTouchEvent(MotionEvent ev);  

 

 

在Activity里,有两个回调函数 :

 

 

[java] view plaincopyAndroid中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解
 
  1. public boolean dispatchTouchEvent(MotionEvent ev);    
  2. public boolean onTouchEvent(MotionEvent ev);    



 

    Android中默认情况下事件传递是由最终的view的接收到,传递过程是从父布局到子布局,也就是从Activity到ViewGroup到View的过程,默认情况,ViewGroup起到的是透传作用。Android中事件传递过程(按箭头方向)如下图,图片来自[qiushuiqifei],谢谢[qiushuiqifei]整理。

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

 

  

    触摸事件是一连串ACTION_DOWN,ACTION_MOVE..MOVE…MOVE、最后ACTION_UP,触摸事件还有ACTION_CANCEL事件。事件都是从ACTION_DOWN开始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,执行super.dispatchTouchEvent(ev),事件向下分发。

    dispatchTouchEvent()返回true,后续事件(ACTION_MOVE、ACTION_UP)会再传递,如果返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。

 

 

下面的几张图参考自[eoe]

 

 

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

 

                                             图1.ACTION_DOWN都没被消费

 

 

 

 

 

                                Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

                                                                  图2-1.ACTION_DOWN被View消费了

 

                                     Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

 

                                                   图2-2.后续ACTION_MOVE和UP在不被拦截的情况下都会去找VIEW

 

                              Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

                                                                    图3.后续的被拦截了

 

                              Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

                                                                       图4ACTION_DOWN一开始就被拦截

 

 

android中的Touch事件都是从ACTION_DOWN开始的:

 

单手指操作:ACTION_DOWN---ACTION_MOVE----ACTION_UP

多手指操作:ACTION_DOWN---ACTION_POINTER_DOWN---ACTION_MOVE--ACTION_POINTER_UP---ACTION_UP.

 

【转】http://blog.****.net/stzy00/article/details/40378533

在布局文件里,假设有3层 , 一层是button, textview等常见组件, 二层是嵌套的RelativeLayout, 三层是LinearLayout, 而一个触摸屏幕的事件无非就是ACTION_DOWN, ACTION_MOVE, ACTION_UP.  而手指从按下到松开离开屏幕, 其实事件分发的传递已经经过了这三层. 这里说下它的处理过程, 也算是巩固记忆了.

 

首先, dispatchTouchEvent(),onInterceptTouchEvent()和onTouchEvent() 这三个方法在每个view都会有, 而无论button,textview还是LinearLayout, RelativeLayout它们最终都继承于View, ViewGroup,因此 这三个方法它们各自都有. dispatchTouchEvent() 负责触摸屏幕事件(down - move - up)的分发, onInterceptTouchEvent()负责事件中的拦截, onTouchEvent()就是事件的处理了.

接着,来说说这三层中各自的三个方法如何参与了这个过程:

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

从Activity开始, 接收到手指按下屏幕的事件,即ACTION_DOWN, 最先到达LinearLayout, LinearLayout调用dispatchTouchEvent(), dispatchTouchEvent()一般不会用于重写, 它会自动分发给onInterceptTouchEvent(),如果onInterceptTouchEvent()的ACTION_DOWN 里面返回fasle就代表自己不处理这个事件,而是交给下一个去处理它, 于是继续把这个事件分发到下一层RelativeLayout, 同理RelativeLayout中如果onInterceptTouchEvent()的ACTION_DOWN依旧返回false的话, 就到达TextView这里. 当TextView的onInterceptTouchEvent())中返回true了 , 就代表由自己来处理这个事件, 也相当于拦截了这个事件.当处理完,返回true就将事件的处理结果逆向提交到Activity中, 告诉Activity自己处理好了. 然后接下来的ACTION_MOVE和ACTION_UP这两个事件才会继续传到TextView中并得到处理.    

假如,刚开始的ACTION_DOWN在RelativeLayout就被处理掉 (即 RelativeLayout中的onInterceptTouchEvent()返回true,交由自己的onTouchEvent()去处理, 下层的TextView就无法参与这次触摸事件的传递分发, 后面的ACTION_MOVE和ACTION_UP, TextView也就无法得到传递).所以如果要拦截某一个TOUCH动作,就在onInterceptTouchEvent()动手吧(嘻嘻,这样说好理解一些嘛.) 只要拦截了ACTION_DOWN,后面的MOVE和UP事件都不会往下传递, 而只拦截MOVE事件, 则UP事件不再往下传递. 但无论是哪个View处理了这次的触摸事件, 其最后处理的结果都必须会逆向地提交到Activity中, 这样用户触摸屏幕的动作才会得到对应的反馈.