我不能在RecyclerView中禁用滚动。我尝试调用rv.setEnabled(false),但我仍然可以滚动。

我如何禁用滚动?


当前回答

通过触摸停止滚动,但通过命令继续滚动:

如果(appTopBarMessagesRV == null) { appTopBarMessagesRV = findViewById(R.id.mainBarScrollMessagesRV);

        appTopBarMessagesRV.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

                if ( rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING)
                {
                     // Stop  scrolling by touch

                    return false;
                }
                return  true;
            }
        });
    }

其他回答

有一种使用标准功能禁用滚动的更直接的方法(从技术上讲,它更确切地说是拦截滚动事件,并在满足条件时结束它)。RecyclerView有一个方法叫做addOnScrollListener(OnScrollListener监听器),使用这个你可以停止滚动,就像这样:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (viewModel.isItemSelected) {
            recyclerView.stopScroll();
        }
    }
});

Use case: Let's say that you want to disable scrolling when you click on one of the items within RecyclerView so you could perform some actions with it, without being distracted by accidentally scrolling to another item, and when you are done with it, just click on the item again to enable scrolling. For that, you would want to attach OnClickListener to every item within RecyclerView, so when you click on an item, it would toggle isItemSelected from false to true. This way when you try to scroll, RecyclerView will automatically call method onScrollStateChanged and since isItemSelected set to true, it will stop immediately, before RecyclerView got the chance, well... to scroll.

注意:为了更好的可用性,尝试使用GestureListener而不是OnClickListener来防止意外点击。

Add

android:descendantFocusability="blocksDescendants"

在你的子SrollView或NestedScrollView(和父ListView, recyclerview和gridview任意一个)

真正的答案是

recyclerView.setNestedScrollingEnabled(false);

文档中的更多信息

为此,您应该重写recycleView的layoutManager。这样它只会禁用滚动,没有其他功能。你仍然能够处理点击或任何其他触摸事件。例如:-

原:

public class CustomGridLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled = true;

    public CustomGridLayoutManager(Context context) {
        super(context);
    }

    public void setScrollEnabled(boolean flag) {
        this.isScrollEnabled = flag;
    }

    @Override
    public boolean canScrollVertically() {
        //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
        return isScrollEnabled && super.canScrollVertically();
    }
}

这里使用“isScrollEnabled”标志,你可以暂时启用/禁用循环视图的滚动功能。

另外:

简单覆盖现有的实现,以禁用滚动和允许单击。

linearLayoutManager = new LinearLayoutManager(context) {
    @Override
    public boolean canScrollVertically() {
        return false;
    }
};

在芬兰湾的科特林:

object : LinearLayoutManager(this) { override fun canScrollVertically() = false }

我在这个问题上纠结了好几个小时, 所以我想分享一下我的经验, 对于layoutManager解决方案,这是很好的,但如果你想重新启用滚动回收器将回到顶部。

到目前为止(至少对我来说)最好的解决方案是使用@Zsolt Safrany方法,但添加getter和setter,这样你就不必删除或添加OnItemTouchListener。

依下列各项

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    boolean isEnable = true;

    public RecyclerViewDisabler(boolean isEnable) {
        this.isEnable = isEnable;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return !isEnable;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {}

   @Override
   public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept){}
 }

使用

RecyclerViewDisabler disabler = new RecyclerViewDisabler(true);
feedsRecycler.addOnItemTouchListener(disabler);

// TO ENABLE/DISABLE JUST USE THIS
disabler.setEnable(enable);