1、跟touch事件相关的三个方法:
用来分派event:
public boolean dispatchTouchEvent(MotionEvent ev);
用来拦截event:
public boolean onInterceptTouchEvent(MotionEvent ev);
用来处理event:
public boolean onTouchEvent(MotionEventev);
2、三个方法的用法:
diapatchTouchEvent():用来分派事件,其中调用了onInterceptTouchEvent()和onToucEvent(),一般不重写该方法。
OnInterceptTouchEvent():用来拦截事件。ViewGroup类中的源码实现就是{returnfalse;},表示不拦截该事件,事件将向下传递(传递给其子View);若手动重写该方法,使其返回true则表示拦截事件,事件将终止向下传递,事件有当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法。
OnTouchEvent():用来处理事件。返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法处理。
下面根据自己写的一个Demo进行具体的分析:
下面是该demo的布局效果图:
其代码如下:
该Activity的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.scrolllayouttest.MainLinearLayout
android:layout_width="400dp"
android:layout_height="400dp"
android:background="#ffcc00">
<com.example.scrolllayouttest.SubLinearLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00cc00">
</com.example.scrolllayouttest.SubLinearLayout>
</com.example.scrolllayouttest.MainLinearLayout>
</LinearLayout>
Activity中的监听代码:
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", " ActivityOne onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "ActivityOne onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "ActivityOne onTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
MainLinearLayout的监听代码:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
// return true;
}
SubLinearLayout的监听代码:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "SubLinearLayout onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "SubLinearLayout onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "SubLinearLayout onTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
// return true;
}
情景一:
可以看到现在所有的事件的传递函数都是默认返回super.onInterceptTouchEvent(ev)或者返回super.onTouchEvent(event);就是表示都不拦截,不处理事件。
运行程序,查看打印的Log信息:
可以分析,按下的ACTION_DOWN事件先是传递到MainLinearLayout的onInterceptTouchEvent中判断是否进行拦截,不拦截则会传递子ViewSubLinearLayout中,在SubLinearLayout中的onInterceptTouchEvent判断是否拦截,不拦截。由于传递到了最后一个View了,所以先由最后一个View的onTouchEvent进行判断,是否处理该事件,由于是SubLinearLayout返回super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于MainLinearLayout的onTouchEvent返回的是super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于没有子View消费该事件,所以事件最后传递到Activity的onTouchEvent中,由Activity进行处理该事件。
情景二:
MainLinearLayout中的监听代码改为:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
// return super.onInterceptTouchEvent(ev);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("Grament0524", "MainLinearLayout onTouchEvent ACTION_UP");
break;
default:
break;
}
<span style="font-family:Droid Sans;">//</span> return super.onTouchEvent(event);
return true;
}
表示MainLinearLayout拦截该事件(在onInterceptTouchEvent中返回true),并且处理该事件(在onTouchEvent中返回true)。
根据其Log,可以分析,事件先是传递到MainLinearLayout的onInterceptTouchEvent中判断是否需要拦截该事件,由于是返回true,所以MainLinearLayout拦截了事件,事件就交由MainLinearLayout的onTouchEvent进行事件的处理了;在MainLinearLayout的onTouchEvent中,由于是返回了true,表示能处理该事件,所以后面的ACTION_MOVE,ACTION_UP都交由MainLinearLayout的onTouchEvent来处理。