一、前言:
事件冲突 肯定牵扯到事件分发 如果你不知道事件分发的流程 建议你阅读我的另一篇文章:
https://blog.csdn.net/qq_32650001/article/details/98726569 (安卓事件分发)
继续~
在安卓开发的过程中 我们会遇到过类似的这几种场景:
1、ScrollView 包裹着ViewPager 当我们横向滑动ViewPager时可能会触发ScrollView竖向滑动。
2、ViewPager 包裹着ViewPager 我们滑动的时候 应该响应哪一个ViewPager呢?
针对上面两种场景 大致可以简化为 :
1、横竖向冲突
2、同向冲突
他们的解决方案有两种 这两种都可以解决上面两种冲突,可以分为:
1、外部解决法
2、外部解决法
二、外部解决法:
什么是外部解决法 ,从外部进行交接判断进行事件拦截 ,我在什么条件下我(父容器)自己拦截处理 ,否则就交给自己的子view处理,这种方式也很简单,也符合事件分发的流程
float lastx = 0.0f;
float lasty = 0.0f;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
boolean intercept = false;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
intercept = false; //down默认不拦截,因为如果down就拦截的话,
// 子view,根本收不到move事件
break;
case MotionEvent.ACTION_MOVE:
if (满足父容器(就是自己)的拦截要求) {
intercept = true;//这个时候就拦截给自己处理
} else
intercept = false;//反之不拦截给子view处理了
break;
case MotionEvent.ACTION_UP:
intercept = false; //up默认不拦截 ,因为如果up拦截的话,会影响
//子view的点击事件,故也不处理啦
break;
}
lastx = x;
lasty = y;
return intercept;
}
二、内部解决法:
这种比较麻烦要同时处理,这个时候主要对子view做文章了 但是同时也要对父容器做点改动
首先看子view
float lastx = 0.0f;
float lasty = 0.0f;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
getParent().requestDisallowInterceptTouchEvent(true); //父布局不要拦截此事件
break;
}
case MotionEvent.ACTION_MOVE: {
float deltaX = x - lastx;
float deltaY = y = lastx;
if (符合父容器需要拦截的事件) {
getParent().requestDisallowInterceptTouchEvent(false); //父布局需要要拦截此事件
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
lastx = x;
lastx = y;
return super.dispatchTouchEvent(ev);
}
父view的改动
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercept = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
intercept = false; //如果是down默认不拦截
break;
}
default:
intercept = true;
break;
}
return intercept;
}
三、总结:
事件冲突大致就是这两种解决方案 上面的代码可以当做模板套用了 至于怎么判断什么时候父容器拦截与否这要靠你自己根据实际场景书写了。
本篇没有进行案例分析 demo编写 大致写了两种事件冲突的解决方案 如有不理解或者错误的地方请留言,拜~