1.解決事件沖突的主要思路
- 1.down事件首先會傳遞到onInterceptTouchEvent()方法
- 2.如果該ViewGroup的OnInterceptTouchEvent()在接收到down事件處理完成之后return false,那么后續(xù)的move,up等事件藤滥,將繼續(xù)會先傳遞給該ViewGroup,之后才和down事件一樣傳遞給最終的目標(biāo)view的onTouchEvent()處理
- 3.如果該ViewGroup的onTnterceptTouchEvent()在接收到down事件處理完成之后return true,那么后續(xù)的move,up等事件境氢,將不再傳遞給onInterceptTouchEvent()椿猎,而是和down事件一樣傳遞給該ViewGroup的onTouchEvent()處理食棕,注意,目標(biāo)view
將接收不到任何事件 - 4.如果最終需要處理事件的view的onTouchEvent()返回了false ,那么該事件將被傳遞至其上一層次的view的onTouchEvent()處理
- 5.如果最終需要處理事件的view 的onTouchEvent()返回了true,那么后續(xù)事件將可以繼續(xù)傳遞給該view的onTouchEvent()處理
2.主要方法:外部攔截法和內(nèi)部攔截法
-
2.1外部攔截法:情景:一個ViewPager嵌套了一個Listview馁痴,一個是左右滑動谊娇,一個上下滑動。這個時候我們可以用外部攔截法,來處理沖突济欢。在父容器ViewPager中赠堵,重寫onInterceptTouchEvent()方法,判斷當(dāng)左右滑動時就攔截事件法褥,上下滑動就不攔截茫叭,將事件交由子元素Listview來處理。首先我們需要重寫一個ViewPager半等,叫MyViewPager揍愁,然后重寫onInterceptTouchEvent()方法。具體代碼如下:
public class MyViewPager extends ViewPager { private int startX; private int startY; public MyViewPager(Context context) { super(context); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: startX= (int) ev.getX(); startY= (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: int dX= (int) (ev.getX()-startX); int dY= (int) (ev.getY()-startX); if(Math.abs(dX)>Math.abs(dY)){//左右滑動 return true; }else {//上下滑動 return false; } case MotionEvent.ACTION_UP: break; } return super.onInterceptTouchEvent(ev); } }
-
2.2內(nèi)部攔截法:情景:一個ViewPager嵌套了一個ViewPager杀饵,兩個都是左右滑動莽囤。這個時候我們可以用內(nèi)部攔截法,來處理沖突切距。即重寫子元素的dispatchTouchEvent()方法朽缎,并調(diào)用getParent().requestDisallowInterceptTouchEvent(true)是父容器不能攔截子元素需要的事件。下面來看具體代碼:
public boolean dispatchTouchEvent(MotionEvent event) { ... switch (action) { case MotionEvent.ACTION_MOVE: getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: if(子元素需要處理此事件) getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_UP: { break; } ... return super.dispatchTouchEvent(event); ; }
案例二:
public class HorizontalScrollViewPager extends ViewPager{
public HorizontalScrollViewPager(Context context) {
super(context);
}
public HorizontalScrollViewPager(Context context, AttributeSet attrs) {
super(context,attrs);
}
private float startX;
private float startY;
/**
* 事件分發(fā)
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// getParent().requestDisallowInterceptTouchEvent(true); //把事件傳遞給自己
switch(ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//一定要把事件給自己
getParent().requestDisallowInterceptTouchEvent(true);
//1.記錄起始坐標(biāo)
startX = ev.getX();
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
//1.來到新的坐標(biāo)
float endX = ev.getX();
float endY = ev.getY(); ev.getRawX();
//2.計算偏移量
float distanceX = endX - startX;
float distanceY = endY - startY;
//3.判斷滑動方向
if(Math.abs(distanceX) > Math.abs(distanceY)) {
//水平方向滑動
//1.如果第0個位置谜悟,并且滑動方向是從左到右滑動
//getParent().requestDisallowInterceptTouchEvent(false);
if(getCurrentItem() == 0 && distanceX >0 ) {
getParent().requestDisallowInterceptTouchEvent(false);
}
// 2.如果是頁簽頁面的最后一個位置话肖,并且滑動方向是從右向左滑動
//getParent().requestDisallowInterceptTouchEvent(false);
else if (getCurrentItem() == (getAdapter().getCount()-1) && distanceX <0) {
getParent().requestDisallowInterceptTouchEvent(false);
}
// 3.其他中間部分
// getParent().requestDisallowInterceptTouchEvent(true);*/
else {
getParent().requestDisallowInterceptTouchEvent(true);
}
} else {
//豎值方向滑動
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
}