解決方案:
1. 外部攔截法
2. 內部攔截法
外部攔截法
指通過父容器進行攔截處理,外部攔截需要重寫父容器的onInterceptTouchEvent
方法,在內部做相應的攔截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;//是否攔截
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
if(父容器當前需要次事件){
intercept = true;
}else{
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
return intercept;
}
注意:
在onInterceptTouchEvent
方法中的ACTION_DOWN 這個事件,父容器必須返回false, 即不攔截ACTION_DOWN事件,這是因爲一旦父容器攔截了ACTION_DOWN,那麼後面的ACTION_MOVE和 ACTION_UP 事件都會直接交由父容器處理,這個時候事件無法再傳遞給子控件,除非不需要子元素處理其他事件
ACTION_MOVE 事件:可以根據需求來決定是否攔截
ACTION_UP 事件:必須返回false,因爲ACTION_UP事件本事沒有太多意義
內部攔截法
是指父容器不攔截任何事件,所有的事件都傳遞給子元素,需要重寫子元素的dispatchTouchEvent
方法,如果子元素需要此事件就直接消耗掉,否則就由父容器進行處理,這種方式跟android的事件分發機制不一致,需要配合getParent().requestDisallowInterceptTouchEvent(true);
方法,除了子元素需要做處理以外,父容器也要默認攔截除了ACTION_DOWN 以外的事件,這樣當子元素調用getParent().requestDisallowInterceptTouchEvent(false);
方法時,父控件才能繼續攔截所需事件
子控件
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
if(父容器需要此類事件){
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
父控件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
return false;
} else {
return true;
}
}
相比之下外部攔截要比內部攔截簡單些