- 滑动冲突的分类
- 滑动的处理规则
- 滑动冲突的解决方式
常见的滑动冲突场景
- 外部布局的滑动方向和内部布局的滑动方向不一致
- 外部滑动方向和内部滑动方向一致
- 上面两种情况的嵌套
场景一:外部控件左右滑动,内部控件上下滑动:类似ViewPager嵌套Fragment(ListView) 场景二:类似ScrollView嵌套ListView
滑动冲突的处理规则
场景一:滑动的角度、距离差和速度差 场景二:业务的划分
滑动冲突的解决方式
- 外部拦截法
事件先经过父容器的拦截处理,重写父容器的onInterceptTouchEvent
方法
- 内部拦截法
重写子元素的dispatchTouchEvent
方法
外部拦截法
java
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: {
intercepted = false;
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
intercepted = true;
}
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastXIntercept;
int deltaY = y - mLastYIntercept;
if (父容器需要拦截的事件规则) {
intercepted = true;
} else {
intercepted = false;
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
Log.d(TAG, "intercepted=" + intercepted);
mLastX = x;
mLastY = y;
mLastXIntercept = x;
mLastYIntercept = y;
return intercepted;
}
内部拦截法
父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器进行处理。
java
public boolean dispatchTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
parent.requestDisallowInterceptTouchEvent(true);
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
Log.d(TAG, "dx:" + deltaX + " dy:" + deltaY);
if (父容器需要当前点击事件) {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(event);
}