我的设置很简单:
<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>
onCreate()
的内容:
layoutManager = new LinearLayoutManager( this );
layoutManager.setOrientation( LinearLayoutManager.HORIZONTAL );
topTopicRecyclerView.setLayoutManager( layoutManager );
现在,当我向左或向右滑动recyclelerView并且滑动角度不是完全水平时,SwipeRefreshLayout会跳入并接管滚动控件。这会导致recyclerView内部出现恼人的视觉“打嗝”。
如果禁用SwipeRefreshLayout,一切都很好。
那么,如何在RecyclerView的区域上停用SwipeRefreshLayout的滚动控件?
答案 0 :(得分:8)
根据this discussion about SRL and HorizontalScrollView,我创建了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 );
}
}
以及XML中的用法:
<com.commons.android.OnlyVerticalSwipeRefreshLayout
android:id="@+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<tags/>
</com.commons.android.OnlyVerticalSwipeRefreshLayout>
答案 1 :(得分:1)
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState == SCROLL_STATE_DRAGGING)
mSwipeToRefresh.setEnabled(false);
if(newState == SCROLL_STATE_IDLE)
mSwipeToRefresh.setEnabled(true);
}
});
答案 2 :(得分:-1)
我从网上获得了一些代码。
将scrollView
更改为特殊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);
}
}
或将RecyclerView
更改为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;
}
}