滑动冲突三种情况
- 外部滑动方式与内部滑动方式不一样.
- 外部滑动方式与内部滑动方式一致.
- 上面两种情况的嵌套.
滑动冲突处理原则
对于上面的第一种情况
记录上次记录点减去当前点得到deltaX,deltaY
对于第二,三种情况
可以 根据业务写出处理规则, 比如当内部View滑动到顶部或者底部时响应外部View,我们就可以根据这个规则判断内部View有没有滑动到底, 如果有的话就不消费事件,没有的话就消费事件.具体怎么消费事件有两种方法.
外部拦截法
所有的事件都要经由decorView分发,所以我们可以在decorView处做文章
如果父View需要事件,就拦截事件;否则就不拦截事件.具体实现在onInterceptTouchEvent()中处理.
public boolean onInterceptTouchEvent(MotionEvent event){
boolean interceptd = false;
int x = (int) event.getX();
int y = (int) event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
interceptd = false;
break;
case MotionEvent.ACTION_MOVE:
if(父容器需要当前点击事件){
interceptd = true;
}else{
interceptd = false;
break;
case MotionEvent.ACTION_UP:
interceptd = false;
break;
default:
break;
mLastXIntercept = x;
mLastYIntercept = y;
return interceptd;
内部拦截法
父容器默认不拦截任何事件,所有事件都交由子元素,子元素不需要再requestDisallowInterceptTouchEvent(boolean)操控父元素处理,和上面的方法正好相反.
Called when a child does not want this parent and its ancestors to intercept touch events with onInterceptTouchEvent(MotionEvent).
disallowIntercept(boolean)
boolean: True if the child does not want the parent to intercept touch events.
public boolean dispatchTouchEvent(MotionEvent event){
int x = (int) event.getX();
int y = (int) event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
操控父元素不拦截ACTION_DOWN,因为ACTION_DOWN不受 ACTION_DISALLOW_INTERCEPT 标记控制,所以一旦父元素拦截ACTION_DOWN,这个事件系列都会被交由父元素处理.
parent.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
int deltaX = X - mLastX;
int deltaY = Y - mLastY;
if(父容器需要此类事件){
parent.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(event);
父元素要做出如下处理
public boolean onInterceptTouchEvent(MotionEvent event){
int action = event.getAction();
if(action == MotionEvent.ACTION_DOWN){
return false;
}else{
return true;
默认拦截除了ACTION_DOWN以外的事件.这样子元素调用requestDisallowInterceptTouchEvent(false)父元素才能继续拦截所需事件???
拦截方法对比
| 拦截方法 | 内部拦截法 | 外部拦截法 |
|---|---|---|
| 定义 | 父元素不拦截任何事件,所有事件都传给子元素 | 父元素需要就直接拦截,不需要就不拦截 |
| 重写 | decorView的onInterceptTouchEvent() |
子View的dispatchTouchEvent |
| 默认 | decorView不拦截ACTION_DOWN,不拦截ACTION_UP(1) |
子元素默认拦截ACTION_DOWN;decorView不拦截ACTION_DOWN,拦截其他的(ACTION_MOVE,ACTION_UP) |