事件分发主要方法
- dispatchTouchEvent(MotionEvent event) 事件分发方法。
- onInterceptTouchEvent(MotionEvent event) 事件拦截方法,只在ViewGroup中。
- onTouchEvent(MotionEvent event) 事件处理方法。
通过Demo来分析
public class DispatchActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("Activity dispatchTouchEvent", event);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("Activity onTouchEvent", event);
return super.onTouchEvent(event);
}
}
ViewGroup dispatchTouchEvent返回true
public class EventViewGroup extends LinearLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup dispatchTouchEvent", event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onInterceptTouchEvent", event);
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onTouchEvent", event);
return super.onTouchEvent(event);
}
}
// 输出日志
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
可见,如果ViewGroup dispatchTouchEvent返回true,则不会执行子View的任何方法,也不会执行ViewGroup的onTouch方法。
ViewGroup dispatchTouchEvent返回true,且onTouch返回true
public class EventViewGroup extends LinearLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup dispatchTouchEvent", event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onInterceptTouchEvent", event);
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onTouchEvent", event);
return true;
}
}
// 输出日志
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
可见,如果ViewGroup dispatchTouchEvent返回true,无论onTouchEvent是否返回true,则不会执行子View的任何方法,也不会执行ViewGroup的onTouch方法。
ViewGroup onInterceptTouchEvent返回true
public class EventViewGroup extends LinearLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup dispatchTouchEvent", event);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onInterceptTouchEvent", event);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onTouchEvent", event);
return super.onTouchEvent(event);
}
}
// 输入日志
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
ViewGroup onTouchEvent ACTION_DOWN
Activity onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
Activity onTouchEvent ACTION_MOVE
......
Activity dispatchTouchEvent ACTION_MOVE
Activity onTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
Activity onTouchEvent ACTION_UP
可见,如果ViewGroup onInterceptTouchEvent返回true,而onTouchEvent返回false,则不会执行子View的任何方法,只会执行一次ViewGroup的onTouchEvent,因为没有返回true,即不处理,则会返回上层Activity执行其onTouchEvent。以后也不会再执行ViewGroup的任何方法。
ViewGroup onInterceptTouchEvent返回true,onTouchEvent返回true
public class EventViewGroup extends LinearLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup dispatchTouchEvent", event);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onInterceptTouchEvent", event);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("ViewGroup onTouchEvent", event);
return true;
}
}
// 输出日志
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
ViewGroup onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onTouchEvent ACTION_UP
可见,如果ViewGroup onInterceptTouchEvent返回true,且onTouchEvent返回true,则不会执行子View的任何方法,而是后续都会执行ViewGroup的onTouchEvent,即由ViewGroup的onTouchEvent来处理后续的事件,且同时也会执行Activity和ViewGroup的dispatchTouchEvent。
View的dispatchTouchEvent返回true
public class EventView extends TextView {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("View onTouchEvent", event);
return super.onTouchEvent(event);
}
}
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onInterceptTouchEvent ACTION_UP
View dispatchTouchEvent ACTION_UP
可见,如果View dispatchTouchEvent返回true,而onTouchEvent返回false,则不会执行View的onTouchEvent,而只会执行View的dispatchTouchEvent。
View的dispatchTouchEvent返回false,而onTouch返回false
public class EventView extends TextView {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("View dispatchTouchEvent", event);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("View onTouchEvent", event);
return super.onTouchEvent(event);
}
}
// 输入日志
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
View onTouchEvent ACTION_DOWN
ViewGroup onTouchEvent ACTION_DOWN
Activity onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
Activity onTouchEvent ACTION_MOVE
......
Activity dispatchTouchEvent ACTION_MOVE
Activity onTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
Activity onTouchEvent ACTION_UP
可见,如果View dispatchTouchEvent返回false,onTouchEvent返回false,只会执行一次View的onTouchEvent,因为没有返回true,即不处理后续的事件,则会返回上层ViewGroup或Activity执行其onTouchEvent。以后也不会再执行View的任何方法。
View的dispatchTouchEvent返回false,而onTouch返回true
public class EventView extends TextView {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Util.printLog("View dispatchTouchEvent", event);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("View onTouchEvent", event);
return true;
}
}
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
View onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onInterceptTouchEvent ACTION_UP
View dispatchTouchEvent ACTION_UP
View onTouchEvent ACTION_UP
可见,View dispatchTouchEvent返回false,onTouchEvent返回true,说明View来处理后续事件,即会执行View的onTouch,不会再调用ViewGroup或Activity。
事件序列如下
事件分发模型如下
结论
即onTouch中在哪消费的Down事件,则后续的MOVE、UP等事件,只会传递到该View,而不会再分发给其子View,所以也不会执行子View的dispatchTouchEvent。
最后介绍下setOnToucheListener、setOnClickListener执行时机
setOnToucheListener
public class EventView extends TextView implements View.OnTouchListener, View.OnClickListener {
private void init() {
setOnTouchListener(this);
setOnClickListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("View onTouchEvent", event);
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Util.printLog("View OnTouchListener onTouch", event);
return false;
}
@Override
public void onClick(View v) {
Util.printLog("View OnClickListener onClick", null);
}
}
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
View OnTouchListener onTouch ACTION_DOWN
View onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
View OnTouchListener onTouch ACTION_MOVE
View onTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onInterceptTouchEvent ACTION_UP
View dispatchTouchEvent ACTION_UP
View OnTouchListener onTouch ACTION_UP
View onTouchEvent ACTION_UP
可见,View 会先执行onTouchListener中的onTouch,如果返回false,则会继续执行onTouchEvent,但不执行onClickListener,因为onTouchEvent返回true。
public class EventView extends TextView implements View.OnTouchListener, View.OnClickListener {
private void init() {
setOnTouchListener(this);
setOnClickListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Util.printLog("View onTouchEvent", event);
return super.onTouchEvent(event);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Util.printLog("View OnTouchListener onTouch", event);
return true;
}
@Override
public void onClick(View v) {
Util.printLog("View OnClickListener onClick", null);
}
}
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
View OnTouchListener onTouch ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
View OnTouchListener onTouch ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onInterceptTouchEvent ACTION_UP
View dispatchTouchEvent ACTION_UP
View OnTouchListener onTouch ACTION_UP
可见,View 会先执行onTouchListener中的onTouch,如果返回true,则不会继续执行onTouchEvent。
setOnToucheListener
只有onTouch和onTouchEvent都返回false,则会执行onClickListenr
Activity dispatchTouchEvent ACTION_DOWN
ViewGroup dispatchTouchEvent ACTION_DOWN
ViewGroup onInterceptTouchEvent ACTION_DOWN
View dispatchTouchEvent ACTION_DOWN
View OnTouchListener onTouch ACTION_DOWN
View onTouchEvent ACTION_DOWN
Activity dispatchTouchEvent ACTION_MOVE
ViewGroup dispatchTouchEvent ACTION_MOVE
ViewGroup onInterceptTouchEvent ACTION_MOVE
View dispatchTouchEvent ACTION_MOVE
View OnTouchListener onTouch ACTION_MOVE
View onTouchEvent ACTION_MOVE
Activity dispatchTouchEvent ACTION_UP
ViewGroup dispatchTouchEvent ACTION_UP
ViewGroup onInterceptTouchEvent ACTION_UP
View dispatchTouchEvent ACTION_UP
View OnTouchListener onTouch ACTION_UP
View onTouchEvent ACTION_UP
View OnClickListener onClick
注意,OnClickListenr.onClick是在执行完ACTION_UP后执行的
最后看下源码
Activity
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
PhoneWindow
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
DecorView 即 ViewGroup
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
}
源码我就不分析了,网上很多文章。