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

我如何禁用滚动?


当前回答

由于setLayoutFrozen已弃用,你可以通过使用suppressLayout冻结你的RecyclerView来禁用滚动。

冻结:

recyclerView.suppressLayout(true)

解冻:

recyclerView.suppressLayout(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);

对于谁想要的只是防止用户滚动RecyclerView,而不松散smoothscrolltopposition或任何其他“去位置”方法,我建议宁愿扩展RecyclerView类,覆盖 onTouchEvent。是这样的:

            public class HardwareButtonsRecyclerView extends RecyclerView {
            
                    public HardwareButtonsRecyclerView(@NonNull Context context) {
                        super(context);
                    }
            
                    public HardwareButtonsRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
                        super(context, attrs);
                    }
            
                    public HardwareButtonsRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                        super(context, attrs, defStyleAttr);
                    }
            
                @Override
                public boolean onTouchEvent(MotionEvent e) {
                    return false;
                }
            }

在Kotlin中,如果你不想为了设置一个值而创建一个额外的类,你可以从LayoutManager创建匿名类:

recyclerView.layoutManager = object : LinearLayoutManager(context) {
    override fun canScrollVertically(): Boolean = 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中启用/禁用滚动。

这是一个空的RecyclerView。OnItemTouchListener窃取每个触摸事件,从而禁用目标RecyclerView。

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

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

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

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

使用它:

RecyclerView rv = ...
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();

rv.addOnItemTouchListener(disabler);        // disables scolling
// do stuff while scrolling is disabled
rv.removeOnItemTouchListener(disabler);     // scrolling is enabled again