android中onInterceptTouchEvent()方法详解

原创 2015年11月18日 12:13:57

这个方法其实以前不怎么关注,后来自定义布局用的多了,发现很多时候都必须要重载这个函数,  


一般重载这个函数地方就是你自定义了一个布局,extends LinearLayout等等布局


一般除了自己的业务处理外,返回值只有两种,

第一种:让父类去处理  返回值,跟踪android源码你会知道返回的是false

作用:让自定义布局上面的所有子view 例如button imageview 等可以被点击

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			downX = (int) ev.getX();
			downY = (int) ev.getY();
			windowX = (int) ev.getX();
			windowY = (int) ev.getY();
			setOnItemClickListener(ev);
		}
		return super.onInterceptTouchEvent(ev);
	}

第二种:直接返回true

作用:让自定义布局上面的所有子view不可以被点击

    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        return true;  
    }

关于这个函数的验证我觉得借用大牛的比较好,如果你想确认这个过程的话,自己再敲一遍,很快就搞定了,我已经搞过

地址:http://blog.csdn.net/vipzjyno1/article/details/21746311

首先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:

[java] view plaincopy
  1. public class MyLayout extends LinearLayout {  
  2.   
  3.     public MyLayout(Context context, AttributeSet attrs) {  
  4.         super(context, attrs);  
  5.     }  
  6.   
  7. }  

然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:

[html] view plaincopy
  1. <com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:id="@+id/my_layout"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <Button  
  9.         android:id="@+id/button1"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="Button1" />  
  13.   
  14.     <Button  
  15.         android:id="@+id/button2"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:text="Button2" />  
  19.   
  20. </com.example.viewgrouptouchevent.MyLayout>  
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
[java] view plaincopy
  1. myLayout.setOnTouchListener(new OnTouchListener() {  
  2.     @Override  
  3.     public boolean onTouch(View v, MotionEvent event) {  
  4.         Log.d("TAG""myLayout on touch");  
  5.         return false;  
  6.     }  
  7. });  
  8. button1.setOnClickListener(new OnClickListener() {  
  9.     @Override  
  10.     public void onClick(View v) {  
  11.         Log.d("TAG""You clicked button1");  
  12.     }  
  13. });  
  14. button2.setOnClickListener(new OnClickListener() {  
  15.     @Override  
  16.     public void onClick(View v) {  
  17.         Log.d("TAG""You clicked button2");  
  18.     }  
  19. });  
我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:

                                      

分别点击一下Button1、Button2和空白区域,打印结果如下所示:


你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。

那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。

查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:

[java] view plaincopy
  1. /** 
  2.  * Implement this method to intercept all touch screen motion events.  This 
  3.  * allows you to watch events as they are dispatched to your children, and 
  4.  * take ownership of the current gesture at any point. 
  5.  * 
  6.  * <p>Using this function takes some care, as it has a fairly complicated 
  7.  * interaction with {@link View#onTouchEvent(MotionEvent) 
  8.  * View.onTouchEvent(MotionEvent)}, and using it requires implementing 
  9.  * that method as well as this one in the correct way.  Events will be 
  10.  * received in the following order: 
  11.  * 
  12.  * <ol> 
  13.  * <li> You will receive the down event here. 
  14.  * <li> The down event will be handled either by a child of this view 
  15.  * group, or given to your own onTouchEvent() method to handle; this means 
  16.  * you should implement onTouchEvent() to return true, so you will 
  17.  * continue to see the rest of the gesture (instead of looking for 
  18.  * a parent view to handle it).  Also, by returning true from 
  19.  * onTouchEvent(), you will not receive any following 
  20.  * events in onInterceptTouchEvent() and all touch processing must 
  21.  * happen in onTouchEvent() like normal. 
  22.  * <li> For as long as you return false from this function, each following 
  23.  * event (up to and including the final up) will be delivered first here 
  24.  * and then to the target's onTouchEvent(). 
  25.  * <li> If you return true from here, you will not receive any 
  26.  * following events: the target view will receive the same event but 
  27.  * with the action {@link MotionEvent#ACTION_CANCEL}, and all further 
  28.  * events will be delivered to your onTouchEvent() method and no longer 
  29.  * appear here. 
  30.  * </ol> 
  31.  * 
  32.  * @param ev The motion event being dispatched down the hierarchy. 
  33.  * @return Return true to steal motion events from the children and have 
  34.  * them dispatched to this ViewGroup through onTouchEvent(). 
  35.  * The current target will receive an ACTION_CANCEL event, and no further 
  36.  * messages will be delivered here. 
  37.  */  
  38. public boolean onInterceptTouchEvent(MotionEvent ev) {  
  39.     return false;  
  40. }  
如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!

好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:

[java] view plaincopy
  1. public class MyLayout extends LinearLayout {  
  2.   
  3.     public MyLayout(Context context, AttributeSet attrs) {  
  4.         super(context, attrs);  
  5.     }  
  6.       
  7.     @Override  
  8.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  9.         return true;  
  10.     }  
  11.       
  12. }  
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:


你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!


看到这里,我相信你对这个函数应该已经的差不多了,

版权声明:本文为博主原创文章,未经博主允许不得转载。

android事件传递机制,以及ondispatchEvent()、onInterceptTouchEvent()和OnTouchEvent()三个方法的作用关系

推荐看以下几篇文章: http://blog.sina.com.cn/s/blog_a0dfaa980100wn1w.html http://www.cnblogs.com/xiaoQLu/arch...

android自定义粘性控件,综合使用measure,layout,onTouchEvent,onInterceptTouchEvent等方法

android自定义粘性控件,综合使用measure,layout,onTouchEvent,onInterceptTouchEvent等方法...

Android事件传递之onInterceptTouchEvent()和requestDisallowInterceptTouchEvent()方法的使用

之前看郭神的事件分发机制解析博客,深入的从源码角度学习了一下Android的事件分发机制。如果还没看过,那么请先去郭神的博客学习下:http://blog.csdn.net/guolin_blog/a...

Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程

上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑。on...

Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的详解

先上这三个事件处理的说明文档: 第一个是:ViewGroup的dispathTouchEvent(MotionEvent ev) : 传递Touch事件至target view(可以是自己)。 ...
  • ihrthk
  • ihrthk
  • 2012年07月28日 00:39
  • 1936

android事件传递机制以及onInterceptTouchEvent()和onTouchEvent()详解二之小秘与领导的故事

总结的不是很好,自己也有点看不懂,正好现在用到了,研究了一个,再次总结,方便大家查看。 总则: 1.onInterceptTouchEvent中有个Intercept,这是什么意思呢?她叫...

探讨Android ViewGroup(Layout)和View中onInterceptTouchEvent和onTouchEvent调用关系详解

本帖记录onInterceptTouchEvent和onTouchEvent调用关系,即各种return true和return false的运行情况。 return true和return f...

浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解

From:http://www.jb51.net/article/35800.htm

Android入门:onInterceptTouchEvent和onTouchEvent调用时序详解 .

onInterceptTouchEvent ()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,...

android事件传递机制以及onInterceptTouchEvent()和onTouchEvent()详解二之小秘与领导的故事

本文转载至:http://www.cnblogs.com/xiaoQLu/archive/2012/04/28/2474443.html请尊重原著 之前写过一个小结  http://www....
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android中onInterceptTouchEvent()方法详解
举报原因:
原因补充:

(最多只允许输入30个字)