一.滑動沖突產(chǎn)生的原因
在界面中,只要內外兩層同時可以滑動,這個時候就會產(chǎn)生滑動沖突。
二.常見的滑動沖突場景
外部滑動和內部滑動方向不一致;
外部滑動方向和內部滑動方向一致;
上面兩種情況的嵌套。
三.滑動沖突的處理規(guī)則
對于場景一,處理的規(guī)則是:當用戶左右(上下)滑動時,需要讓外部的View攔截點擊事件,當用戶上下(左右)滑動的時候,需要讓內部的View攔截點擊事件。根據(jù)滑動的方向判斷誰來攔截事件。
對于場景二,由于滑動方向一致,這時候只能在業(yè)務上找到突破點,根據(jù)業(yè)務需求,規(guī)定什么時候讓外部View攔截事件,什么時候由內部View攔截事件。
場景三的情況相對比較復雜,同樣根據(jù)需求在業(yè)務上找到突破點。
四.滑動沖突的解決方式
1.外部攔截法:所謂的外部攔截法是指點擊事件都先經(jīng)過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截,外部攔截器需要重寫父容器的onInterceptTouchEvent方法,在內部做出相應的攔截。下面是偽代碼:
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:
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:
if (父容器需要當前事件) {
intercepted = true;
} else {
intercepted = flase;
}
break;
}
case MotionEvent.ACTION_UP:
intercepted = false;
break;
default : break;
}
mLastXIntercept = x;
mLastYIntercept = y;
return intercepted;
}
2.內部攔截法:內部攔截法是指父容器不攔截任何事件,所有的事件都傳遞給子元素,如果子元素需要此事件就直接消耗,否則就交由父容器進行處理。這種方法與Android事件分發(fā)機制不一致,需要配合requestDisallowInterceptTouchEvent方法才能正常工作。下面是偽代碼:
public boolean dispatchTouchEvent ( MotionEvent event ) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction) {
case MotionEvent.ACTION_DOWN:
parent.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (父容器需要此類點擊事件) {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
default : break;
}
mLastX = x;
mLastY = y;
return super.dispatchTouchEvent(event);
}
除了子元素需要做處理外,父元素也要默認攔截除了ACTION_DOWN以外的其他事件,這樣當子元素調用parent.requestDisallowInterceptTouchEvent(false)方法時,父元素才能繼續(xù)攔截所需的事件。因此,父元素要做以下修改:+
public boolean onInterceptTouchEvent (MotionEvent event) {
int action = event.getAction();
if(action == MotionEvent.ACTION_DOWN) {
return false;
} else {
return true;
}
}