事件分发机制是一个很重要的东西。废话不多说,接下来我便跟着任教主的步伐走一走。
public boolean dispatchTouchEvent(MotionEvent ev)
用来进行事件分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。
public boolean onIntereceptTouchEvent(MotionEvent event)
在上述方法中被调用,用来判断是否拦截某个事件,如果拦截了,那么同一事件序列中,此方法不会被再次调用。返回结果表示是否拦截当前事件
public boolean onTouchEvent(MotionEvent event)
在dispatchTouchEvent中调用,用来处理点击时间,返回结果表示是否消耗当前事件,如果不消耗,则同一事件序列中,当前view无法 再次收到事件。
看如下精辟的伪代码
public boolean dispatchTouchEvent(MotionEvent ev){
boolean consume = false;
if(onIntereceptTouchEvent(ev)){
consume = onTouchEvent(ev);
}else{
consume = child.dispatchTouchEvent(ev);
}
return consume;
}
对于一个根ViewGroup来说,点击事件产生后,首先会传递给他,dispatch就会被调用,如果onInterecept返回true,就表示要拦截,那么事件就会由viewgroup来处理。如果返回false,就表示不拦截,那么就传递给子view。
TouchListener>onTouch>onClickListener 优先级
Activity->window->view
如果一个view的onTouch返回false,那么他的父容器就会调用onTouchEvent。
看看主席的总结吧:
事件分发机制源码解析
任玉刚大神
郭霖大神-1
郭霖大神-2
张鸿洋
在界面中出现上下2层都可以滑动的时候就会出现滑动冲突。常见的滑动冲突的场景都三种
那么我们如何解决呢?我们可以判断手指x、y方向上的速度或者移动距离,根据速度差或者距离差来处理。
解决方式:
在父控件中拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercepted = false ;
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//如果正在滑动,就不拦截down事件,如果滑动结束了,就拦截
intercepted = false;
if (!mScroller.isFinished()){
mScroller.abortAnimation();
intercepted = true;
}
break;
case MotionEvent.ACTION_MOVE:
//如果x方向上偏移量大,就判定为x,拦截
int deltaX = x-mLastXIntercept;
int deltaY = y-mLastYIntercept;
if (Math.abs(deltaX)>Math.abs(deltaY)){
intercepted = true;
}else{
intercepted = false;
}
break;
case MotionEvent.ACTION_UP:
intercepted = false;
break;
default:
break;
}
Log.e(TAG, "intercepted=" + intercepted);
mLastX = x;
mLastY = y;
mLastXIntercept = x;
mLastYIntercept = y;
return intercepted;
}
public boolean onInterceptTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN){
mLastX =x;
mLastY = y;
if (!mScroller.isFinished()){
mScroller.abortAnimation();
return true;
}
return false;
}else{
return true;
}
}
view中
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mHorizontalScrollViewEx2.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x-mLastX;
int deltaY = y-mLastY;
if (Math.abs(deltaX)>Math.abs(deltaY)){
mHorizontalScrollViewEx2.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(event);
}
代码就是上面哪些,其实不难。更多的东西,请去看书。