1、首先我们自定义一个LinearLayout和Button,然后在里面复写dispatchTouchEvent、onInterceptTouchEvent(Button没有这个函数)、onTouchEvent这三个函数。
其中dispatchTouchEvent函数是用来分发事件的,onInterceptTouchEvent事件是用来判断是否拦截事件的,onTouchEvent则用来处理具体事物。
package com.tang.Javen;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class TouchEventLinearLayout extends LinearLayout
{
public TouchEventLinearLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout onTouchEvent");
return super.onTouchEvent(event);
}
}
package com.tang.Javen;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
public class TouchEventButton extends Button
{
public TouchEventButton(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
System.out.println("TouchEventButton dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
System.out.println("TouchEventButton onTouchEvent");
return super.onTouchEvent(event);
}
}
2、然后在Activity中复写dispatchTouchEvent、onTouchEvent,查看log
<?xml version="1.0" encoding="utf-8"?>
<com.tang.Javen.TouchEventLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.tang.Javen.TouchEventButton
android:id="@+id/btu1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="button_01"/>
</com.tang.Javen.TouchEventLinearLayout>
package com.tang.Javen;
import android.app.Activity;
public class ViewGroupTouchEventActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("ViewGroupTouchEventActivity dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
System.out.println("ViewGroupTouchEventActivity onTouchEvent");
return super.onTouchEvent(event);
}
}
运行起来
点击Activity,查看打印
从打印中可以看出onTouchEvent事件是从Activity的dispatchTouchEvent函数传入到LinearLayout的dispatchTouchEvent中去的。
然后我们来分析各个函数的返回值对事件传递的影响:
1、把ViewGroupTouchEventActivity中的dispatchTouchEvent返回值改为true或者false,查看打印。
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("ViewGroupTouchEventActivity dispatchTouchEvent");
//return super.dispatchTouchEvent(ev);
return true;
}
这里可以看到当dispatchTouchEvent返回true或者false时,则这TouchEvent事件就不会传递下去了,这里打印两次是一个DOWN事件和一个UP事件。只有return super.dispatchTouchEvent(ev)时事件才会被分发下去。
然后这个事件就会传递到ViewGroup的dispatchTouchEvent中继续分发。
2、当把TouchEventLinearLayout中的dispatchTouchEvent返回为true时,DOWN和UP事件不会继续分发下去,既不向上也不向下传递。
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout dispatchTouchEvent");
// return super.dispatchTouchEvent(ev);
return true;
}
3、把TouchEventLinearLayout中的dispatchTouchEvent返回改为false时
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout dispatchTouchEvent");
// return super.dispatchTouchEvent(ev);
// return true;
return false;
}
查看打印可以知道,当TouchEventLinearLayout中的dispatchTouchEvent返回为false时,DOWN事件则不会再向下传递了,而是直接返回到上层Activiy中去,而UP事件则不经过TouchEventLinearLayout,而是直接在Activity中接收了。
4、当TouchEventLinearLayout中的dispatchTouchEvent的返回值为super.dispatchTouchEvent时,则会询问该ViewGroup中的onInterceptTouchEvetn,如果onInterceptTouchEvent返回true时,则说明该ViewGroup拦截此次TouchEvent,交给该ViewGroup的onTouchEvent进行处理,如果返回false的话,则说明不会拦截此次的TouchEvent,并且继续向下传递,询问下一层ViewGroup的dispatchTouchEvent。
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
// return true;
// return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventLinearLayout onInterceptTouchEvent");
// return super.onInterceptTouchEvent(ev);
return true;
// return false;
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
System.out.println("TouchEventLinearLayout onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("TouchEventLinearLayout onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("TouchEventLinearLayout onTouchEvent ACTION_UP");
break;
default:
break;
}
// return super.onTouchEvent(event);
return true;
// return false;
}
当该ViewGroup的onTouchEvent返回为true时,则DOWN、MOVE、UP事件就都在该ViewGroup中的onTouchEvent事件中接收
当该ViewGroup的onTouchEvent返回为false或者super.onTouchEvent(event)时,则DOWN事件会在该ViewGroup中接收,然后向上传递上去,然后之后的MOVE、UP事件则不经过该ViewGroup,直接在上层Activity接收
5、当在ViewGroup中的dispatchTouchEvent的返回值为super.dispatchTouchEvent,且该ViewGroup的onInterceptTouchEvent返回false或者super.onInterceptTouchEvent时,则事件继续向下传递,然后当TouchEventButton中的dispatchTouchEvent返回true时。
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
System.out.println("TouchEventButton dispatchTouchEvent");
// return super.dispatchTouchEvent(event);
return true;
}
当事件分发到View是,如果view的dispatchTouchEvent返回的是true,则事件不再分发。
当view的dispatchTouchEvent返回为false时,则DOWN事件向上传递到上层的onTouchEvent事件中去,如果上层onTouchEvent事件返回false或者super.onTouchEvent,则继续向上传递,而MOVE、UP则直接在最终接收事件层中接收,否则所有事件都在上层的onTouchEvent中接收。
当view的dispatchTouchEvent返回为super.dispatchTouchEvent时,则事件传递到该View的onTouchEvent事件中去,如果该View中的onTouchEvent返回true或者super.onTouchEvent,则DOWN、MOVE、UP事件全部在该View的onTouchEvent事件中接收了。
当View中的onTouchEvent返回false时,则该View中接收DOWN事件后,会继续向上传递,然后查看上层的onTouchEvent的返回值,以此类推,MOVE、UP事件则直接在上层接收不经过该View
6、添加一个TouchEventRelativeLayout继承RelativeLayout
package com.tang.Javen;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
public class TouchEventRelativeLayout extends RelativeLayout
{
public TouchEventRelativeLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventRelativeLayout dispatchTouchEvent");
// return super.dispatchTouchEvent(ev);
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
// TODO Auto-generated method stub
System.out.println("TouchEventRelativeLayout onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
System.out.println("TouchEventRelativeLayout onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("TouchEventRelativeLayout onTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("TouchEventButton onTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.tang.Javen.TouchEventLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.tang.Javen.TouchEventRelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.tang.Javen.TouchEventButton
android:id="@+id/btu1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="button_01" />
</com.tang.Javen.TouchEventRelativeLayout>
</com.tang.Javen.TouchEventLinearLayout>
当事件分发到这个RelativeLayout的dispatchTouchEvent时,当该dispatchTouchEvent返回false时,向上传递,然后它是判断上层的onTouchEvent的返回值来决定事件在哪里接收。
总结:
1、当dispatchTouchEvent返回true时,则停止分发;当dispatchTouchEvent返回false时,则向上传递,然后根据上层的onTouchEvent事件的返回值决定事件在哪接收;当dispatchTouchEvent返回super.dispatchTouchEvent时,则继续传递。
如果该层是ViewGroup,则判断该层的onInterceptTouchEvent,如果onInterceptTouchEvent返回true,则事件直接在该层的onTouchEvent中接收,如果返回false或者super.onInterceptTouchEvent则继续向下传递,以此类推。
如果该层是View,则直接在该层的onTouchEvent中判断返回值进行接收。
2、在onTouchEvent事件中,如果返回true,则所有的事件在该onTouchEvent接收;如果返回false则会继续向上传递,然后判断上层的onTouchEvent的返回值,以此类推。
3、DOWN事件会随着事件分发在走,当确定了具体在哪个onTouchEvent事件中接收后,MOVE和UP事件就直接到该onTouchEvent事件中去接收了。
4、onTouchEvent的返回值中,ViewGroup的返回值为false和super.onTouchEvent效果一样;View中的返回值为true和super.onTouchEvent效果一样。
流程图下载:http://download.csdn.net/detail/hedaogelaoshu/7933063
代码下载:http://download.csdn.net/detail/hedaogelaoshu/7933081