android中onInterceptTouchEvent()方法详解
2015-11-18 12:13
483 查看
这个方法其实以前不怎么关注,后来自定义布局用的多了,发现很多时候都必须要重载这个函数,
一般重载这个函数地方就是你自定义了一个布局,extends LinearLayout等等布局
一般除了自己的业务处理外,返回值只有两种,
第一种:让父类去处理 返回值,跟踪android源码你会知道返回的是false
作用:让自定义布局上面的所有子view 例如button imageview 等可以被点击
第二种:直接返回true
作用:让自定义布局上面的所有子view不可以被点击
关于这个函数的验证我觉得借用大牛的比较好,如果你想确认这个过程的话,自己再敲一遍,很快就搞定了,我已经搞过
地址:http://blog.csdn.net/vipzjyno1/article/details/21746311
首先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:
[java] view
plaincopy
public class MyLayout extends LinearLayout {
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:
[html] view
plaincopy
<com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/my_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button2" />
</com.example.viewgrouptouchevent.MyLayout>
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
[java] view
plaincopy
myLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "myLayout on touch");
return false;
}
});
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button1");
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button2");
}
});
我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:
![](http://img.blog.csdn.net/20130629142303734?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
分别点击一下Button1、Button2和空白区域,打印结果如下所示:
![](http://img.blog.csdn.net/20130629144048875?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。
那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。
查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:
[java] view
plaincopy
/**
* Implement this method to intercept all touch screen motion events. This
* allows you to watch events as they are dispatched to your children, and
* take ownership of the current gesture at any point.
*
* <p>Using this function takes some care, as it has a fairly complicated
* interaction with {@link View#onTouchEvent(MotionEvent)
* View.onTouchEvent(MotionEvent)}, and using it requires implementing
* that method as well as this one in the correct way. Events will be
* received in the following order:
*
* <ol>
* <li> You will receive the down event here.
* <li> The down event will be handled either by a child of this view
* group, or given to your own onTouchEvent() method to handle; this means
* you should implement onTouchEvent() to return true, so you will
* continue to see the rest of the gesture (instead of looking for
* a parent view to handle it). Also, by returning true from
* onTouchEvent(), you will not receive any following
* events in onInterceptTouchEvent() and all touch processing must
* happen in onTouchEvent() like normal.
* <li> For as long as you return false from this function, each following
* event (up to and including the final up) will be delivered first here
* and then to the target's onTouchEvent().
* <li> If you return true from here, you will not receive any
* following events: the target view will receive the same event but
* with the action {@link MotionEvent#ACTION_CANCEL}, and all further
* events will be delivered to your onTouchEvent() method and no longer
* appear here.
* </ol>
*
* @param ev The motion event being dispatched down the hierarchy.
* @return Return true to steal motion events from the children and have
* them dispatched to this ViewGroup through onTouchEvent().
* The current target will receive an ACTION_CANCEL event, and no further
* messages will be delivered here.
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!
好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:
[java] view
plaincopy
public class MyLayout extends LinearLayout {
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:
![](http://img.blog.csdn.net/20130629145544984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lueXU4OTA4MDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!
看到这里,我相信你对这个函数应该已经的差不多了,
一般重载这个函数地方就是你自定义了一个布局,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
public class MyLayout extends LinearLayout {
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:
[html] view
plaincopy
<com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/my_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button2" />
</com.example.viewgrouptouchevent.MyLayout>
可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:
[java] view
plaincopy
myLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "myLayout on touch");
return false;
}
});
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button1");
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button2");
}
});
我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:
分别点击一下Button1、Button2和空白区域,打印结果如下所示:
你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。
那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。
查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:
[java] view
plaincopy
/**
* Implement this method to intercept all touch screen motion events. This
* allows you to watch events as they are dispatched to your children, and
* take ownership of the current gesture at any point.
*
* <p>Using this function takes some care, as it has a fairly complicated
* interaction with {@link View#onTouchEvent(MotionEvent)
* View.onTouchEvent(MotionEvent)}, and using it requires implementing
* that method as well as this one in the correct way. Events will be
* received in the following order:
*
* <ol>
* <li> You will receive the down event here.
* <li> The down event will be handled either by a child of this view
* group, or given to your own onTouchEvent() method to handle; this means
* you should implement onTouchEvent() to return true, so you will
* continue to see the rest of the gesture (instead of looking for
* a parent view to handle it). Also, by returning true from
* onTouchEvent(), you will not receive any following
* events in onInterceptTouchEvent() and all touch processing must
* happen in onTouchEvent() like normal.
* <li> For as long as you return false from this function, each following
* event (up to and including the final up) will be delivered first here
* and then to the target's onTouchEvent().
* <li> If you return true from here, you will not receive any
* following events: the target view will receive the same event but
* with the action {@link MotionEvent#ACTION_CANCEL}, and all further
* events will be delivered to your onTouchEvent() method and no longer
* appear here.
* </ol>
*
* @param ev The motion event being dispatched down the hierarchy.
* @return Return true to steal motion events from the children and have
* them dispatched to this ViewGroup through onTouchEvent().
* The current target will receive an ACTION_CANCEL event, and no further
* messages will be delivered here.
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!
好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:
[java] view
plaincopy
public class MyLayout extends LinearLayout {
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:
你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!
看到这里,我相信你对这个函数应该已经的差不多了,
相关文章推荐
- 54、Android 粒子效果之雨(下雨的效果)
- Android 内核解剖 - AMS(Activity Manager Service)
- Android编程实现QQ表情的发送和接收完整实例(附源码)
- Android开发教程:数据储存之SharedPreferences
- 关于在5.0上沉浸式布局虚拟按键的问题
- 关于Android生命周期方法调用return的问题
- 说说Android无限轮播的那些事
- android源码浅析--AlertController
- Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
- Android开发中常用adb命令
- android根据屏幕宽度,按比例缩放图片
- android图片压缩质量参数Bitmap.Config RGB_565等的含义
- Android获取设备信息
- Android与Java在编译及类库方面的主要区别
- Android编程常用技巧实例总结
- Android的内存机制
- Android Service完全解析,关于服务你所需知道的一切(下)
- 一键分析Android的BugReport
- Android自定义屏幕侧边字母排序控件
- Android Service完全解析,关于服务你所需知道的一切(上)