1、外部拦截法 (子view代码无需修改)(符合view事件分发机制)
说明:需要在父ViewGroup,重写onInterceptTouchEvent方法,根据业务需要,判断哪些事件是父Viewgroup需要的,需要的话就对该事件进行拦截,然后交由onTouchEvent方法处理,若不需要,则不拦截,然后传递给子view或子viewGroup,
代码:
public boolean onInterceptTouchEvent(MotionEvent ev) {
int y= (int) ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
yDown=y;
isIntercept=false;
break;
case MotionEvent.ACTION_MOVE:
yMove=y;
if (yMove-yDown<0){ //根据业务需求更改判断条件,判断是时候需要拦截
isIntercept=false;
}else if(yMove-yDown>0&&getChildAt(0).getScrollY()==0){
isIntercept=true;
}else if(yMove-yDown>0&&getChildAt(0).getScrollY()>0){
isIntercept=false;
}
break;
case MotionEvent.ACTION_UP:
isIntercept=false;
break;
}
return isIntercept; //返回true表示拦截,返回false表示不拦截
}
2、内部拦截法(父viewgroup需要重写onInterceptTouchEvent)(不符合view事件分发机制)
说明:顾名思义就是在子view中拦截事件,父viewGroup默认是不拦截任何事件的,所以,当事件传递到子view时,
子view根据自己的实际情况来,如果该事件是需要子view来处理的,那么子view就自己消耗处理,如果该事件不需要由子view来处理,那么就调用getParent().requestDisallowInterceptTouchEvent()方法来通知父viewgroup来拦截
这个事件,也就是说,叫父容器来处理这个事件,这刚好和view的分发机制相反。
代码: **(需要注意,要确保MotionEvent.ACTION_DOWN时不拦截)**
//子view的代码·
public boolean dispatchTouchEvent(MotionEvent ev) {
int y= (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
yDown=y;
break;
case MotionEvent.ACTION_MOVE:
yMove=y;
Log.e("mes",yMove+"!!!");
int scrollY = getScrollY();
if (scrollY == 0&&yMove-yDown>0) { //根据业务需求判断是否需要通知父viewgroup来拦截处理该事件
//允许父View进行事件拦截
Log.e("mes",yMove-yDown+"拦截");
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
//父viewgroup代码 (要确保down是不拦截,move和up时要拦截)
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(ev.getAction()==MotionEvent.ACTION_DOWN){
return false;
}else{
return true;
}
}