1. 常见滑动冲突场景
- 外部滑动方向和内部滑动方向不一致
如外部ViewPager左右滑动,内部ListView上下滑动 - 外部滑动方向和内部滑动方向一致
如ScrollView嵌套ListView,条件1ScrollView滚动,条件2ListView滚动 - 以上两种混合
2. 滑动冲突解决方式一:外部拦截法
int mLastInterceptX = 0;
int mLastInterceptY = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercepted = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 这里必须返回false,因为这里如果父View拦截了,子View收不到后续事件,
// 应该让子View拿到Down事件,父View拦截Move事件。
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:
// 这里根据条件判断是否需要拦截
if (父容器需要当前事件条件满足){
intercepted = true;
}else {
intercepted = false;
}
break;
case MotionEvent.ACTION_UP:
// 这里返回false,因为up没什么意义了
intercepted = false;
break;
case MotionEvent.ACTION_CANCEL:
break;
}
mLastInterceptX = x;
mLastInterceptY = y;
return super.onInterceptTouchEvent(ev);
}
3. 滑动冲突内部拦截法
这种方法主要利用子元素的以下方法
getParent().requestDisallowInterceptTouchEvent(true);
重写子元素的dispatchTouchEvent方法
int mLastX,mLastY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
// True if the child does not want the parent to intercept touch events.
// down时不希望父Veiw拦截,父View拦截后,后续事件无法传到子View中
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (父容器需要此类点击事件的条件满足){
// false 子类希望父View拦截(disallowIntercept,不允许拦截,不拦截为true则不拦截,为false则拦截)
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
}
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(ev);
}
父容器做如下修改
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN){
// down时不拦截
return false;
}
// 其他拦截
return true;
}
网友评论