解决ViewPager与RecyclerView等的滑动冲突-新闻详情

解决ViewPager与RecyclerView等的滑动冲突


发布时间:2017-11-28责任编辑:朱明 浏览:10481


Android开发中经常碰到滑动冲突的问题,比如RecyclerView等垂直刷新的控件内嵌ViewPager,当手指斜着滑动RecyclerView时,便会引起RecyclerView的刷新,两者出现了滑动冲突,解决的方法如下:

 

1:从RecyclerView的角度出发:

Android的事件分发是从下到上的,父布局先分发到触摸事件,所以可以此时在父布局的

onInterceptTouchEvent中判断,当x轴的滑动距离大于y轴的滑动距离时,不拦截事件,
将事件交给子View去处理。
2:从ViewPager的角度出发:
同理,不处理父View,当x轴的滑动距离大于y轴的滑动距离时拦截事件,同时告诉父View不要拦截,代码如下:
/**
 *
事件拦截
 
* @param ev
 
* @return
 
*/

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

   
int x = (int)ev.getX();
   
int y = (int)ev.getY();

   
switch (ev.getAction()){

       
case MotionEvent.ACTION_DOWN:
            Log.i(
"CustomViewPager:","Intercept_ACTION_DOWN");
           
mLastX = x;
           
mLastY = y;
           
break;
       
case MotionEvent.ACTION_MOVE:
            Log.i(
"CustomViewPager:","Intercept_ACTION_MOVE");
           
int dx = Math.abs(x - mLastX);
           
int dy = Math.abs(y - mLastY);

           
if(dx * 4 > dy){
               
// 上一页
               
if(x >= mLastX){
                   
return ViewCompat.canScrollHorizontally(this,-1);
                }
else {
                   
// 下一页
                   
return ViewCompat.canScrollHorizontally(this,1);
                }
            }
           
break;
    }

   
return super.onInterceptTouchEvent(ev);
}

/**
 *
事件分发
 
* @param ev
 
* @return
 
*/

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

   
int x = (int)ev.getX();
   
int y = (int)ev.getY();

   
switch (ev.getAction()){

       
case MotionEvent.ACTION_DOWN:
            Log.i(
"CustomViewPager:","dispatch_ACTION_DOWN");
           
mLastX = x;
           
mLastY = y;
            getParent().requestDisallowInterceptTouchEvent(
true);
           
break;
       
case MotionEvent.ACTION_MOVE:
            Log.i(
"CustomViewPager:","dispatch_ACTION_MOVE");
           
int dx = Math.abs(x - mLastX);
           
int dy = Math.abs(y - mLastY);

           
if(dx * 4 > dy){
               
if(x >= mLastX){
                   
// 上一页
                   
if(ViewCompat.canScrollHorizontally(this,-1)){
                        getParent().requestDisallowInterceptTouchEvent(
true);
                    }
else {
                        getParent().requestDisallowInterceptTouchEvent(
false);
                    }
                }
else {
                   
// 下一页
                   
if(ViewCompat.canScrollHorizontally(this,1)){
                        getParent().requestDisallowInterceptTouchEvent(
true);
                    }
else {
                        getParent().requestDisallowInterceptTouchEvent(
false);
                    }
                }
            }
else {
                getParent().requestDisallowInterceptTouchEvent(
false);
            }
           
break;
       
case MotionEvent.ACTION_UP:
       
case MotionEvent.ACTION_CANCEL:
            Log.i(
"CustomViewPager:","ACTION_UP/ACTION_CANCEL");
            getParent().requestDisallowInterceptTouchEvent(
false);
           
break;
    }

   
return super.dispatchTouchEvent(ev);
}
 
同时重写dispatchTouchEvent与onInterceptTouchEvent,getParent().requestDisallowInterceptTouchEvent(true);用于告诉父View不要拦截此次触摸事件,ViewCompat.canScrollHorizontally(this,-1);用于判断ViewPager是否滑动到了左右边界,以防ViewPager内嵌ViewPager时滑动到边界后不能继续滑动的问题。



诚信工作室   供稿