此篇文章用内部拦截法解决内外View滑动方向不一致的冲突问题
1. 重写ListView如下
public class ListViewEx extends ListView {
int mLastX,mLastY;
public ListViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
@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 (Math.abs(deltaX)>Math.abs(deltaY)){
// 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);
}
}
2. 外部HorizontalScrollViewEx修改拦截方法
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
mLastX = x;
mLastY = y;
if (!mscroller.isFinished()) {
mscroller.abortAnimation();
return true;
}
return false;
} else {
return true;
}
}
HorizontalScrollViewEx中的onTouchEvent方法是处理它应有的效果的,如左右滚动(move)时,View要左右跟着滚动。松开手指时(up),要根据速度判断,自动滚到下一页或上一页。
3. 外部拦截法和内部拦截法的区别
外部拦截法符合事件的分发流程,简单。内部拦截法尽管也能实现,但稍显复杂,建议使用外部拦截法。