请简要描述一下事件分发机制,并说明onInterceptTouchEvent和onTouchEvent的作用和关系
Android的事件分发机制也是View和ViewGroup的事件的分发和处理,当用户手指接触到屏幕以后,所产生的一系列事件中,都被android包装成MotionEvent,由三种事件类型组成,ACTION_DOWN,ACTION_MOVE,ACTION_UP,
顺序是activity,再到viewGroup,再传递到View
由三种方法dispatchTouchEvent(),onInterceptTouchEvent,onTouchEvent所处理,dispatchTouchEvent的作用是分发传递点击事件,当点击事件能够传递给当前的View的时候,该方法都会被调用,onInterceptTouchEvent的作用是拦截事件,只存在ViewGroup中,在ViewGroup的dispatchTouchEvent中调用,如果onInterceptTouchEvent return true那么事件不会再传递下去,就让当前view的ontouchEvent来处理
onTouchEvent的作用的是处理点击事件
我们看一个例子:public class EventTest extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.event_test);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_MOVE:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_UP:
Log.d("TAG","<<<<
break;
}
return false;
}
}
xml文件:<?xml version="1.0" encoding="utf-8"?>
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#FF00FF"
android:layout_centerInParent="true"/>
ParentView:public class ParentView extends RelativeLayout {
public ParentView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 方法用户拦截被传递过来的事件,用于判断被传递过来的事件是否需要被当前的view进行处理
* return true : 拦截该事件,将该事件交给当前view的onTouchEvent方法进行处理
* return false和super.interceptTouchEvent(ev),事件将不会被拦截,会被分发到子控件中)
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_MOVE:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_UP:
Log.d("TAG","<<<<
break;
}
return false;
}
}
运行结果是:
触摸蓝色的框的区域:
这个时候打印的结果是<<<<
<<<<
<<<<
<<<<
public ChildView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* 当前的view把事件进行了拦截,则事件则会被传递到该方法中
* return false:表明没有消费该事件,事件将会以冒泡的方式一直被传递到上层的view或Activity中的
* return true: 表明消费了该事件,事件到此结束。
* return super.onTouchEvent(event):默认情况,和return false一样。
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_MOVE:
Log.d("TAG","<<<<
break;
case MotionEvent.ACTION_UP:
Log.d("TAG","<<<<
break;
}
return true;
}
}
如果我们把parentView的onInterceptTouchEvent return false
那么childView的onTouchEvent return true,那么打印的结果是<<<<
<<<<
<<<<
如果我们把childView的ontouchEvent return false<<<<
<<<<
<<<<
<<<<
<<<<