Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解
2015-04-28 14:48
357 查看
参考文档: http://hao3100590.iteye.com/blog/1267294 /article/9458253.html首先,看Android的官方文档正解onInterceptTouchEvent()与onTouchEvent()的机制: 1. down事件首先会传递到onInterceptTouchEvent()方法 2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false, 那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最 终的目标view的onTouchEvent()处理 3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true, 那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样 传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。 4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一 层次的view的onTouchEvent()处理 5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递 给该view的onTouchEvent()处理这是官方文档的说法,要是自己没亲自去写个程序观察哈,基本上没法理解,所以上程序先,然后分析:布局文件main.xml
</pre><pre name="code" class="html"><span style="font-size: small;"><?xml version="1.0" encoding="utf-8"?><com.hao.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><com.hao.LayoutView2android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent" android:gravity="center"><com.hao.MyTextViewandroid:layout_width="wrap_content" android:layout_height="wrap_content"android:id="@+id/tv" android:text="AB" android:textSize="40sp"android:textStyle="bold" android:background="#FFFFFF"android:textColor="#0000FF" /></com.hao.LayoutView2></com.hao.LayoutView1></span>第一层自定义布局LayoutView1.java
<span style="font-size: small;">package com.hao;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;public class LayoutView1 extends LinearLayout {private final String TAG = "LayoutView1";public LayoutView1(Context context, AttributeSet attrs) {super(context, attrs);Log.e(TAG,TAG);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {int action = ev.getAction();switch(action){case MotionEvent.ACTION_DOWN:Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN");// return true; 在这就拦截了,后面的就不会得到事件break;case MotionEvent.ACTION_MOVE:Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP");break;case MotionEvent.ACTION_CANCEL:Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");break;}return false;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();switch(action){case MotionEvent.ACTION_DOWN:Log.e(TAG,"onTouchEvent action:ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:Log.e(TAG,"onTouchEvent action:ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG,"onTouchEvent action:ACTION_UP");break;case MotionEvent.ACTION_CANCEL:Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");break;}return true;// return false;}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// TODO Auto-generated method stubsuper.onLayout(changed, l, t, r, b);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);}}</span>第二层布局LayoutView2.java
<span style="font-size: small;">package com.hao;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;public class LayoutView2 extends LinearLayout {private final String TAG = "LayoutView2";public LayoutView2(Context context, AttributeSet attrs) {super(context, attrs);Log.e(TAG,TAG);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {int action = ev.getAction();switch(action){case MotionEvent.ACTION_DOWN:Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN");// return true;break;case MotionEvent.ACTION_MOVE:Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP");break;case MotionEvent.ACTION_CANCEL:Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");break;}return false;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();switch(action){case MotionEvent.ACTION_DOWN:Log.e(TAG,"onTouchEvent action:ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:Log.e(TAG,"onTouchEvent action:ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG,"onTouchEvent action:ACTION_UP");break;case MotionEvent.ACTION_CANCEL:Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");break;}// return true;return false;}}</span>自定义MyTextView.java
<span style="font-size: small;">package com.hao;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.TextView;public class MyTextView extends TextView {private final String TAG = "MyTextView";public MyTextView(Context context, AttributeSet attrs) {super(context, attrs);Log.e(TAG,TAG);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();switch(action){case MotionEvent.ACTION_DOWN:Log.e(TAG,"onTouchEvent action:ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:Log.e(TAG,"onTouchEvent action:ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG,"onTouchEvent action:ACTION_UP");break;case MotionEvent.ACTION_CANCEL:Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");break;}return false;// return true;}public void onClick(View v) {Log.e(TAG, "onClick");}public boolean onLongClick(View v) {Log.e(TAG, "onLongClick");return false;}}</span>其实代码很简单,就是自定义了View,在View里面都重写了interceptTouchEvnet (),和onTouchEvent(),然后测试其返回值,对监听的影响,关键是自己动手,逐个测试,并预测结果,等你能预测结果的时候,也就懂了,需要修改的地方就是interceptTouchEvnet 和onTouchEvent的返回值,他们决定了事件监听的流程,下面我画了一张图,如有不足之处欢迎指正,谢谢!下面是我的正解:基本的规则是:*1.down事件首先会传递到onInterceptTouchEvent()方法** 2.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false(不拦截),* 那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。** 3.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true(拦截,那么后面的move,up事件不需要在看因为已经拦截了, 我们直接拿去处理onTouchEvent()就可以了),那么后续的move, up等事件将不再传递给onInterceptTouchEvent(), 而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。下面例子演示:* 1:LayoutView1(31375): onInterceptTouchEvent action:ACTION_DOWN* 2:LayoutView2(31375): onInterceptTouchEvent action:ACTION_DOWN* 3:LayoutView2(31375): onTouchEvent action:ACTION_DOWN* 4:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE* 5:LayoutView2(31375): onTouchEvent action:ACTION_MOVE* 6:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE* 7:LayoutView2(31375): onTouchEvent action:ACTION_MOVE* 8:LayoutView1(31375): onInterceptTouchEvent action:ACTION_UP* 9:LayoutView2(31375): onTouchEvent action:ACTION_UP* 该设置为:* onInterceptTouchEvent:LayoutView1为false,LayoutView2为true* onTouchEvent:LayoutView2为true* 故而事件在LayoutView2(onInterceptTouchEvent:返回true)时被拦截并处理,根据上面说法就是LayoutView2后续的MOVE,UP操作都不在经过onInterceptTouchEvent,直接* 交给onTouchEvent处理,结果也的确如此。(见:LayoutView2的3,5,7,9,第一次是onInterceptTouchEvent处理如1,以后交给onTouchEvent)* 而LayoutView1都还是要经过onInterceptTouchEvent(见LayoutView1的4,6,8)** 4.如果最终需要处理事件的view的onTouchEvent()返回了false(没能处理这个事件,不能丢在传回来让父继续),* 那么该事件将被传递至其上一层次的view的onTouchEvent()处理。* *************************************************************************** 感觉像是一个圈,然后一直在找一个能处理这个消息的人,如果找到了就结束,没找到就循环,直到回到发出消息的那个人* 注(对下面):没有标注的DOWN表示拦截事件onInterceptTouchEvent,标注了onTouchEvent就是处理事件* a.如果都没处理(onInterceptTouchEvent返回false):A(DOWN)-->B(DOWN)-->C(onTouchEvent DOWN)-->B(onTouchEvent DOWN)-->A(onTouchEvent DOWN),没有执行UP事件,注意有MOVE的话,在DOWN和UP之间,下面的都一样。*b. B处理(B的onInterceptTouchEvent返回true):A(DOWN)-->B(DOWN)-->B(onTouchEvent)-->A(onTouchEvent UP)-->B(onTouchEvent UP)-->(over)*形象说明:如果父亲不拦截消息就传给儿子,如果儿子要这个消息就处理(DOWN),结束,然后有父亲1--父亲2--儿子以此释放消息(UP)。 然是如果儿子对这个消息置之不理,那这个消息又传回父亲,由父亲来处理即。下面给出了5中情况(不拦截表示onInterceptTouchEvent返回false):* 11** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return true)--结束* 22** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return true)--结束* 33** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束(如果都没处理不在执行UP ACTION)* 44** 父亲1(LayoutView1拦截true)--父亲1(onTouchEvent return true)--结束 (DOWN--DOWN(onTouchEvent)--UP(onTouchEvent))* 55** 父亲1(LayoutView1拦截false)--父亲2(LayoutView2拦截true)--父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束 (DOWN1--DOWN2--DOWN(2 onTouchEvent)--DOWN(1 onTouchEvent)--UP(1 onTouchEvent))(1:父亲2,2:父亲2)** **************************************************************************** 5.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。*/下面给出一张处理的流程图:下附源代码: http://hao3100590.iteye.com/blog/1267294
相关文章推荐
- Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解
- Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解
- Android事件dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent、OnTouchListener调用关系
- Android点击事件onTouchEvent与onInterceptTouchEvent传递关系-只需要理解5点
- android事件传递机制,以及ondispatchEvent()、onInterceptTouchEvent()和OnTouchEvent()三个方法的作用关系
- 细说Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)
- android触摸事件传递机制以及onInterceptTouchEvent()和onTouchEvent()总结
- android ViewGroup的onInterceptTouchEvent 和 onTouchEvent事件
- android 事件处理--onInterceptTouchEvent和onTouchEvent调用时序(二)
- android事件传递机制以及onInterceptTouchEvent()和onTouchEvent()详解二之小秘与领导的故事
- 细说Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)
- Android 触摸事件的分发与处理流程:onInterceptTouchEvent和onTouchEvent
- Android onInterceptTouchEvent与onTouchEvent调用关系
- Android onTouchEvent和onInterceptTouchEvent事件分发详解(一)
- android事件传递机制以及onInterceptTouchEvent()和OnTouchEvent()详解三之ACTION_CANCEL事件和事件回传
- android开发步步为营之65:解决ScrollView和ListView触摸事件onInterceptTouchEvent相互冲突问题
- requestDisallowInterceptTouchEvent(),onInterceptTouchEvent()等事件方法-Android
- android事件传递机制以及onInterceptTouchEvent()和OnTouchEvent()详解三之ACTION_CANCEL事件和事件回传
- (转)Android ViewGroup的onInterceptTouchEvent()事件分析
- Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent