一、事件滑动
二、拦截机制
1.外部拦截
2.内部拦截
三、案例
1.ViewPage 嵌套 ListView滑动冲突
1、外部拦截解决 ——重写viewpage 的onInterceptTouchEvent
// 外部拦截法:父容器处理冲突
// 我想要把事件分发给谁就分发给谁
private int mLastX, mLastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// if (event.getAction() == MotionEvent.ACTION_DOWN){
// super.onInterceptTouchEvent(event);
// return false;
// }
// return true;
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastX = (int) event.getX();
mLastY = (int) event.getY();
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
return true;
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
return super.onInterceptTouchEvent(event);
}
2、内部拦截解决
1.重写viewpage 的onInterceptTouchEvent
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
super.onInterceptTouchEvent(event);
return false;
}
return true;
}
2.重写Listview的dispatchTouchEvent
内部拦截法:子view处理事件冲突
private int mLastX, mLastY;
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
getParent().requestDisallowInterceptTouchEvent(true);
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(event);
}
2.SwipeRefreshLayout嵌套 ViewPager滑动冲突
1、外部拦截解决 ——重写SwipeRefreshLayout 的onInterceptTouchEvent
//外部拦截
private int mLastX, mLastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
//外部拦截 y>x 说明竖直滑动,进行拦截 否则不拦截
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastX = (int) event.getX();
mLastY = (int) event.getY();
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (Math.abs(deltaY) > Math.abs(deltaX)) {
return true;
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
default:
break;
}
return super.onInterceptTouchEvent(event);
}
2、内部拦截解决 ——重写SwipeRefreshLayout 的onInterceptTouchEvent
1.重写SwipeRefreshLayout 的onInterceptTouchEvent
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
super.onInterceptTouchEvent(event);
return false;
}
return true;
}
2.重写ViewPager的dispatchTouchEvent
//内部拦截
private float startX;
private float startY;
private float x;
private float y;
private float deltaX;
private float deltaY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = ev.getX();
startY = ev.getY();
ViewCompat.setNestedScrollingEnabled(this,true);
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
x = ev.getX();
y = ev.getY();
deltaX = Math.abs(x - startX);
deltaY = Math.abs(y - startY);
if (deltaX < deltaY) {
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return super.dispatchTouchEvent(ev);
}
因为SwipeRefreshLayout重写了requestDisallowInterceptTouchEvent方法:
public void requestDisallowInterceptTouchEvent(boolean b) {
if ((VERSION.SDK_INT >= 21 || !(this.mTarget instanceof AbsListView)) && (this.mTarget == null || ViewCompat.isNestedScrollingEnabled(this.mTarget))) {
super.requestDisallowInterceptTouchEvent(b);
}
}
所以 ViewCompat.isNestedScrollingEnabled(this.mTarget)) 返回为true时才能有效;所以调用前添加
ViewCompat.setNestedScrollingEnabled(this,true);