SwipeRefreshLayout blocking horizontally scrolled RecyclerView

你。 提交于 2019-12-20 02:41:15

问题


My setup is simple enough:

<android.support.v4.widget.SwipeRefreshLayout
     android:id="@+id/swiperefresh"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >

     <android.support.v7.widget.RecyclerView
         android:id="@+id/recyclerView"
         android:layout_width="match_parent"
         android:layout_height="220dp"/>

</android.support.v4.widget.SwipeRefreshLayout>

The content of onCreate():

layoutManager = new LinearLayoutManager( this );
layoutManager.setOrientation( LinearLayoutManager.HORIZONTAL );
topTopicRecyclerView.setLayoutManager( layoutManager );

Now, when I swipe the recyclerView left or right and the swipe angle is not perfectly horizontal, the SwipeRefreshLayout jumps in and takes over the scrolling control. That leads to annoying visual "hiccups" inside the recyclerView.

If the SwipeRefreshLayout is disabled, all is fine.

So, how can I deactivate the SwipeRefreshLayout's scrolling control over the RecyclerView's area?


回答1:


As per this discussion about SRL and HorizontalScrollView, I created the counterpart for the SwipeRefreshLayout:

public class OnlyVerticalSwipeRefreshLayout extends SwipeRefreshLayout {

  private int touchSlop;
  private float prevX;
  private boolean declined;

  public OnlyVerticalSwipeRefreshLayout( Context context, AttributeSet attrs ) {
    super( context, attrs );
    touchSlop = ViewConfiguration.get( context ).getScaledTouchSlop();
  }

  @Override
  public boolean onInterceptTouchEvent( MotionEvent event ) {
    switch( event.getAction() ){
      case MotionEvent.ACTION_DOWN:
        prevX = MotionEvent.obtain( event ).getX();
        declined = false; // New action
        break;

      case MotionEvent.ACTION_MOVE:
        final float eventX = event.getX();
        float xDiff = Math.abs( eventX - prevX );
        if( declined || xDiff > touchSlop ){
          declined = true; // Memorize
          return false;
        }
        break;
    }
    return super.onInterceptTouchEvent( event );
  }
}

and usage in XML:

<com.commons.android.OnlyVerticalSwipeRefreshLayout
     android:id="@+id/swiperefresh"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >

   <tags/>

</com.commons.android.OnlyVerticalSwipeRefreshLayout>



回答2:


I get some code from net.

Change scrollView to Special scrollview:

package com.image.indicator.control;  

import android.content.Context;  
import android.util.AttributeSet;  
import android.view.MotionEvent;  
import android.widget.ScrollView;  

/** 


 * @File: ScrollViewExtend.java 

 * @Package com.image.indicator.control 

 * @Author Hanyonglu 

 * @Date 2012-6-18 

 * @Version V1.0 
 */  
public class ScrollViewExtend extends ScrollView {  

    private float xDistance, yDistance, xLast, yLast;  

    public ScrollViewExtend(Context context, AttributeSet attrs) {  
        super(context, attrs);  
    }  

    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        switch (ev.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                xDistance = yDistance = 0f;  
                xLast = ev.getX();  
                yLast = ev.getY();  
                break;  
            case MotionEvent.ACTION_MOVE:  
                final float curX = ev.getX();  
                final float curY = ev.getY();  

                xDistance += Math.abs(curX - xLast);  
                yDistance += Math.abs(curY - yLast);  
                xLast = curX;  
                yLast = curY;  

                if(xDistance > yDistance){  
                    return false;  
                }    
        }  

        return super.onInterceptTouchEvent(ev);  
    }  
}  

Or change RecyclerView to ViewPager:

public class ChildViewPager extends ViewPager{  
    /** 触摸时按下的点 **/  
    PointF downP = new PointF();  
    /** 触摸时当前的点 **/  
    PointF curP = new PointF();   
    OnSingleTouchListener onSingleTouchListener;  

    public ChildViewPager(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        // TODO Auto-generated constructor stub  
    }  

    public ChildViewPager(Context context) {  
        super(context);  
        // TODO Auto-generated constructor stub  
    }  

    @Override  
    public boolean onInterceptTouchEvent(MotionEvent arg0) {  
        // TODO Auto-generated method stub  
        //当拦截触摸事件到达此位置的时候,返回true,  
        //说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent  
        return true;  
    }  

    @Override  
    public boolean onTouchEvent(MotionEvent arg0) {  
        // TODO Auto-generated method stub  
        //每次进行onTouch事件都记录当前的按下的坐标  
        curP.x = arg0.getX();  
        curP.y = arg0.getY();  

        if(arg0.getAction() == MotionEvent.ACTION_DOWN){  
            //记录按下时候的坐标  
            //切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变  
            downP.x = arg0.getX();  
            downP.y = arg0.getY();  
            //此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰  
            getParent().requestDisallowInterceptTouchEvent(true);  
        }  

        if(arg0.getAction() == MotionEvent.ACTION_MOVE){  
            //此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰  
            getParent().requestDisallowInterceptTouchEvent(true);  
        }  

        if(arg0.getAction() == MotionEvent.ACTION_UP){  
            //在up时判断是否按下和松手的坐标为一个点  
            //如果是一个点,将执行点击事件,这是我自己写的点击事件,而不是onclick  
            if(downP.x==curP.x && downP.y==curP.y){  
                onSingleTouch();  
                return true;  
            }  
        }  

        return super.onTouchEvent(arg0);  
    }  

        /** 
     * 单击 
     */  
    public void onSingleTouch() {  
        if (onSingleTouchListener!= null) {  

            onSingleTouchListener.onSingleTouch();  
        }  
    }  

    /** 
     * 创建点击事件接口 
     * @author wanpg 
     * 
     */  
    public interface OnSingleTouchListener {  
        public void onSingleTouch();  
    }  

    public void setOnSingleTouchListener(OnSingleTouchListener onSingleTouchListener) {  
        this.onSingleTouchListener = onSingleTouchListener;  
    }  

}  


来源:https://stackoverflow.com/questions/34136178/swiperefreshlayout-blocking-horizontally-scrolled-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!