我有一个RecyclerView
,其中包含一个方向为HORIZONTAL
的LinearLayoutManager
。它中的每个条目都可以拥有交互式元素(包括垂直的ScrollView
)。有没有一种简单的方法让RecyclerView
在不截断子视图的触碰事件的情况下忽略用户水平滚动或甩动?
我正在以编程方式控制RecyclerView
的滚动,这很好用,直到用户将其甩开。
我尝试了一些非常简单的东西,想法是当我对某个事件做出反应调用smoothScrollToPosition
时,我启用滚动并禁用触碰事件,直到滚动解决。像这样:
private class NoScrollHorizontalLayoutManager extends LinearLayoutManager {
ScrollingTouchInterceptor interceptor = new ScrollingTouchInterceptor();
protected boolean canScroll;
public NoScrollHorizontalLayoutManager(Context ctx) {
super(ctx, LinearLayoutManager.HORIZONTAL, false);
}
public RecyclerView.OnItemTouchListener getInterceptor() {
return interceptor;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
canScroll = true;
super.smoothScrollToPosition(recyclerView, state, position);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if(state == RecyclerView.SCROLL_STATE_IDLE) {
canScroll = false;
}
}
@Override
public boolean canScrollHorizontally() {
return canScroll;
}
public class ScrollingTouchInterceptor implements RecyclerView.OnItemTouchListener {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return canScrollHorizontally();
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
并且像这样使用它...
NoScrollHorizontalLayoutManager layout = new NoScrollHorizontalLayoutManager(context);
recycler.setLayoutManager(layout);
recycler.addOnItemTouchListener(layout.getInterceptor());
实际上,这个方法 几乎 可以工作...但是在平滑滚动时,如果点击屏幕仍然会破坏程序化滚动。显然我漏掉了一些明显的东西,或者有更聪明的方法来解决这个问题。 更新:非RecyclerView的解决方案可以在这里找到: 如何禁用ViewPager中的手势滑动,但仍然能够编程滑动?
/**
* ViewPager that doesn't allow swiping.
*/
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}