一.外部攔截
屬於事件分發的正常套路,需要攔截就攔截,不需要就不攔截
@Override
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:
case MotionEvent.ACTION_UP:
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:
if(父佈局需要滑動)
intercepted = true;
else
intercepted = false;
break;
default:
break;
}
mLastX = x;
mLastY = y;
return intercepted;
}
二.內部攔截
逆向的,控制父view不攔截事件,然後子view根據情況控制父view去攔截
分析
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
解讀1: mFirstTouchTarget != null 當父view將事件傳遞給子view處理時,此條件成立。
由此可見第一個if判斷中,事件不由子view處理以及事件爲move或者up事件時,將不會走判斷,直接攔截事件,也因此攔截了down事件後其他事件也都交由其處理。
解讀2: FLAG_DISALLOW_INTERCEPT標示位,用於子view控制父view的攔截情況使用(通過對requestDisallowInterceptTouchEvent的設置,控制邏輯是否走進判斷中,通過對父view的onInterceptTouchEvent方法的重寫,進而控制父view是否攔截事件)
具體思路:
down事件下來後爲了父view不攔截事件,在子view中down事件調用getParent().requestDisallowInterceptTouchEvent(true)使得父View不會攔截其他move、up事件。然後子view會根據自己的實際情況調getParent().requestDisallowInterceptTouchEvent(false)讓父view走進判斷中,因爲重寫了父view的onInterceptTouchEvent方法,當爲非down事件的時候進行攔截。
實現如下:
父View:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
return false;//不攔截down事件
} else {
return true;//攔截除down事件之外的其他事件
}
}
子View
@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;
default:
break;
}
//這裏不能返回false
return super.dispatchTouchEvent(ev);
}
喵印~~