我实现了新的SwipeRefreshLayout
成分在我的应用程序,它与任何垂直意见工作得很好,比如ListView
,GridView
和ScrollView
.
它在水平视图中表现得很糟糕,比如HorizontalScrollView
.向右或向左滚动时,SwipeRefreshLayout
视图会缓存触摸,阻止HorizontalScrollView
接收并开始垂直滚动以执行刷新.
我尝试解决这个问题,因为我之前解决了ScrollView
与ViewPager
内部垂直问题,使用requestDisallowInterceptTouchEvent
但它没有用.我还注意到,在原始SwipeRefreshLayout
类中重写此方法而不返回super.谷歌的开发者留下了评论" //Nope.
":)
因为SwipeRefreshLayout
组件相对较新,我找不到修复水平滚动问题的解决方案,同时仍然允许滑动刷新视图以跟踪和处理垂直滚动,所以我想我会分享我的解决方案,希望它会让人节省一个小时或两个.
如果您没有记住已经拒绝了ACTION_MOVE事件的事实,那么如果用户返回到您的初始mPrevX附近,您最终会在以后使用它.
只需添加一个布尔值来记住它.
public class CustomSwipeToRefresh extends SwipeRefreshLayout { private int mTouchSlop; private float mPrevX; // Indicate if we've already declined the move event private boolean mDeclined; public CustomSwipeToRefresh(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPrevX = MotionEvent.obtain(event).getX(); mDeclined = false; // New action break; case MotionEvent.ACTION_MOVE: final float eventX = event.getX(); float xDiff = Math.abs(eventX - mPrevX); if (mDeclined || xDiff > mTouchSlop) { mDeclined = true; // Memorize return false; } } return super.onInterceptTouchEvent(event); } }
我通过扩展SwipeRefreshLayout
和覆盖它来解决它onInterceptTouchEvent
.在里面,我计算用户徘徊的X距离是否大于触摸坡度.如果是,则表示用户正在水平滑动,因此我返回false
,让孩子查看(HorizontalScrollView
在这种情况下)获取触摸事件.
public class CustomSwipeToRefresh extends SwipeRefreshLayout { private int mTouchSlop; private float mPrevX; public CustomSwipeToRefresh(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPrevX = MotionEvent.obtain(event).getX(); break; case MotionEvent.ACTION_MOVE: final float eventX = event.getX(); float xDiff = Math.abs(eventX - mPrevX); if (xDiff > mTouchSlop) { return false; } } return super.onInterceptTouchEvent(event); } }