Touch事件

来源:互联网 发布:c语言编程软件下载win7 编辑:程序博客网 时间:2024/04/29 05:03

点击事件的处理包括三个函数:

分别为传递——dispatchTouchEvent()函数、拦截——onInterceptTouchEvent()函数、消费——onTouchEvent()函数

拥有这三个方法的类:
Activity类:ActivitydispatchTouchEvent();
onTouchEvent();
View容器(ViewGroup的子类):FrameLayout、LinearLayout……
ListView、ScrollVIew……
dispatchTouchEvent();
onInterceptTouchEvent();
onTouchEvent();
View控件(非ViewGroup子类):Button、TextView、EditText……dispatchTouchEvent();
onTouchEvent();

个方法的用法:
dispatchTouchEvent()用来分派事件。
其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法
onInterceptTouchEvent()用来拦截事件。
ViewGroup类中的源码实现就是{return false;}表示不拦截该事件,
事件将向下传递(传递给其子View);
若手动重写该方法,使其返回true则表示拦截,事件将终止向下传递,
事件由当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法
onTouchEvent()用来处理事件。
返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);
返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法来处理

传递流程

(1) 事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。

(2) 事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。

(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。

(4) 如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。

(5) OnTouchListener 优先于 onTouchEvent()对事件进行消费。
上面的消费即表示相应函数返回值为 true。

即Touch事件的传递是由最顶层的ViewGroup -》 View的,Touch的处理是由最内层的View向顶层传递的

通过实例来解析


第一种情况,LinearLayout的onInterceptTouchEvent方法返回false,onTouchEvent返回true,Button的onTouchEvent也返回true

public class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch(event.getAction()){case MotionEvent.ACTION_DOWN:System.out.println("MyLInearLaout: actiondown");}return true;}}

public class MyButton extends Button {public MyButton(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("MYbutton pressed");break;default:break;}return true;<pre name="code" class="java"><span style="white-space:pre"></span>}
}


这种情况下,事件的传递是由MyLinearLayout传递给MyButton的(即传递是由视图树的顶层向下传递的),由于MyLinearLayout没有重新onInterceptTouchEvent方法,所以Touch事件并别有被拦截,所以Touch事件由MyButton来处理,MyButton的onTouchEvent方法返回为true表示该事件被它消费掉了,不会在向上传递了(向上指的是视图树),所以MyLinearLayout的onTouchEvent方法就不会被执行了

第二种情况就是MyButton的onTouchEvent方法返回false

<span style="color:#333333;">public class MyButton extends Button {public MyButton(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("MYbutton pressed");break;default:break;}return </span><span style="color:#ff6666;">false</span><span style="color:#333333;">;}}</span>

Touch事件由上向下传递到了MyButton,由于MyButton已经是树的最下端了,所以就会执行MyButton的onTouchEvent方法,虽然这里该方法被执行了,但是onTouchEvent返回false,所以该Touch事件没有被消费掉,那么Touch事件就会调转向上传递,传递到了MyLinearLayout,就会执行它的onTouchEvent方法,该方法返回true,所以该Touch事件就被消费掉了,不会再向上传递了

第三种情况:MyLinearLayout重写了onInterceptTouchEvent方法,并返回true,对Touch事件进行了拦截

<span style="font-size:18px;">public class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch(event.getAction()){case MotionEvent.ACTION_DOWN:System.out.println("MyLInearLaout: actiondown");}return true;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return <span style="color:#ff0000;">true</span>;}}</span>
Touch事件传递到MyLinearLayout时,由于onInterceptTouchEvent方法返回true,所以该事件就被拦截了,不会在向下传递了,MyLinearLayout就相当于到了树的最下端,那么就会执行它的onTouchEvent方法,而它的onTouchEvent方法返回true,所以该Touch事件就被消费掉了


参考:

http://blog.csdn.net/morgan_xww/article/details/9372285

http://a.codekk.com/detail/Android/Trinea/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20View%20%E4%BA%8B%E4%BB%B6%E4%BC%A0%E9%80%92

http://blog.csdn.net/cyp331203/article/details/45071069



<pre name="code" class="java">

0 0