前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android中onInterceptTouchEvent()方法详解

android中onInterceptTouchEvent()方法详解

作者头像
wust小吴
发布2019-07-08 16:23:49
2.9K0
发布2019-07-08 16:23:49
举报
文章被收录于专栏:风吹杨柳

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

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

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

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

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

代码语言:javascript
复制
	@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不可以被点击

代码语言:javascript
复制
    @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. public MyLayout(Context context, AttributeSet attrs) {  
  3. super(context, attrs);  
  4.     }  
  5. }  

然后,打开主布局文件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. <Button
  8. android:id="@+id/button1"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:text="Button1" />
  12. <Button
  13. android:id="@+id/button2"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:text="Button2" />
  17. </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. public MyLayout(Context context, AttributeSet attrs) {  
  3. super(context, attrs);  
  4.     }  
  5. @Override
  6. public boolean onInterceptTouchEvent(MotionEvent ev) {  
  7. return true;  
  8.     }  
  9. }  

现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015年11月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档