如何禁用RecyclerView滚动?

Zso*_*any 193 android scroll android-recyclerview

我无法禁用滚动RecyclerView.我试着打电话rv.setEnabled(false)但我仍然可以滚动.

如何禁用滚动?

小智 338

您应该覆盖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();
 }
}
Run Code Online (Sandbox Code Playgroud)

在这里使用"isScrollEnabled"标志,您可以临时启用/禁用回收视图的滚动功能.

也:

简单覆盖现有实现以禁用滚动并允许单击.

 linearLayoutManager = new LinearLayoutManager(context) {
 @Override
 public boolean canScrollVertically() {
  return false;
 }
};
Run Code Online (Sandbox Code Playgroud)

  • 禁用在默认LayoutManger上滚动应该已经存在,API的用户不应该这样做.谢谢你的回答! (7认同)
  • 这应该是正确的答案,因为它在允许我单击的同时禁用滚动。 (5认同)
  • 你添加kotlin版本对象:LinearLayoutManager(this){override fun canScrollVertically():Boolean {return false}} (4认同)
  • 这也会禁用smoothScrollToPosition (2认同)

Boz*_*jsa 125

真正的答案是

recyclerView.setNestedScrollingEnabled(false);
Run Code Online (Sandbox Code Playgroud)

更多信息在文档中

  • 这将仅禁用嵌套滚动,而不是所有滚动.特别是,如果您的RecyclerView在ScrollView中但没有填满屏幕,ScrollView将不会滚动(内容适合屏幕),您将在RecyclerView中获得滚动UI(尝试滚动时列表效果结束) )即使它变大也不会滚动.扩展LayoutManager确实可以胜任. (31认同)
  • 这对我来说很好,但是我的"RecyclerView"在使用"ScrollView"的Fragment布局中,所以我不得不通过"NestedScrollView"更改"ScrollView",如下所述:/sf/answers/2666223171/ (5认同)
  • @ personne3000我相信recyclerView.setHasFixedSize(true)可以完成这项工作.编辑:我也将它与setFillViewport(true)结合使用,所以我实际上并不确定这两个中哪一个修复了它. (3认同)

Mil*_*nia 53

对于API 21及更高版本:

不需要java代码. 你可以android:nestedScrollingEnabled="false" 在xml中设置 :

<android.support.v7.widget.RecyclerView
     android:id="@+id/recycler"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clipToPadding="true"
     android:nestedScrollingEnabled="false"
     tools:listitem="@layout/adapter_favorite_place">
Run Code Online (Sandbox Code Playgroud)

  • 我认为这应该是公认的答案,在课堂上没有任何努力你可以禁用滚动,但布局中允许触摸. (6认同)
  • 您还应该突出显示与您的答案相关的注意事项。android:nestedScrollingEnabled="false" 将使 onBindViewHolder 一次调用所有项目,并且这些项目不会被回收,如果数据很大,这不好。 (4认同)
  • 嗯,这行不通。我想这只适用于嵌套视图。但recyclerview本身仍然是可滚动的。 (3认同)

Zso*_*any 46

这有点hackish解决方法,但它的工作原理; 你可以启用/禁用滚动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) {

    }
}
Run Code Online (Sandbox Code Playgroud)

使用它:

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 
Run Code Online (Sandbox Code Playgroud)

  • 这会禁用项目点击吗? (8认同)
  • 这也会禁用父视图的滚动 (2认同)

小智 33

这对我有用:

  recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
Run Code Online (Sandbox Code Playgroud)

  • This disables all touch. (10认同)

Shy*_*dda 16

由于setLayoutFrozen已被弃用,您可以禁用通过使用冷冻的RecyclerView滚动suppressLayout

冻结:

recyclerView.suppressLayout(true)
Run Code Online (Sandbox Code Playgroud)

解冻:

recyclerView.suppressLayout(false)
Run Code Online (Sandbox Code Playgroud)


小智 12

创建扩展RecyclerView类的类

public class NonscrollRecylerview extends RecyclerView {

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

    public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}
Run Code Online (Sandbox Code Playgroud)

这将禁用滚动事件,但不会禁用单击事件

在XML中使用它执行以下操作:

  <com.yourpackage.xyx.NonscrollRecylerview 
     ...
     ... 
  />
Run Code Online (Sandbox Code Playgroud)


Vir*_*ngh 12

您可以通过冻结RecyclerView来禁用滚动。

冻结: recyclerView.setLayoutFrozen(true)

要解冻: recyclerView.setLayoutFrozen(false)

  • 请注意:当 RecyclerView 被冻结时,子视图不会更新。当屏幕上有足够的空间来显示所有项目时,我需要禁用滚动。哦......这个任务多么好的Android API...... (3认同)

Emi*_*Raz 12

有一个非常简单的答案。

LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
                @Override
                public boolean canScrollVertically() {
                    return false;
                }
            };
Run Code Online (Sandbox Code Playgroud)

上面的代码禁用 RecyclerView 垂直滚动。


Ekt*_*sar 11

如果你只是禁用滚动功能,RecyclerView那么你可以使用setLayoutFrozen(true);方法RecyclerView.但它不能禁用触摸事件.

your_recyclerView.setLayoutFrozen(true);
Run Code Online (Sandbox Code Playgroud)


Mic*_*cer 9

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

recyclerView.layoutManager = object : LinearLayoutManager(context) {
    override fun canScrollVertically(): Boolean = false
}
Run Code Online (Sandbox Code Playgroud)


小智 7

recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            // Stop only scrolling.
            return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
        }
    });
Run Code Online (Sandbox Code Playgroud)


jaf*_*ech 7

在 XML 中:-

你可以加

android:nestedScrollingEnabled="false"

在子 RecyclerView 布局 XML 文件中

或者

在 Java 中:-

childRecyclerView.setNestedScrollingEnabled(false);

到您的 RecyclerView 中的 Java 代码。

使用 ViewCompat (Java) :-

childRecyclerView.setNestedScrollingEnabled(false);仅适用于android_version>21设备。要在所有设备上工作,请使用以下内容

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);


小智 5

扩展LayoutManager和覆盖canScrollHorizontally()canScrollVertically()禁用滚动。

请注意,在开头插入项目不会自动回滚到开头,要解决此问题,请执行以下操作:

  private void clampRecyclerViewScroll(final RecyclerView recyclerView)
  {
    recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
    {
      @Override
      public void onItemRangeInserted(int positionStart, int itemCount)
      {
        super.onItemRangeInserted(positionStart, itemCount);
        // maintain scroll position at top
        if (positionStart == 0)
        {
          RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
          if (layoutManager instanceof GridLayoutManager)
          {
            ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }else if(layoutManager instanceof LinearLayoutManager)
          {
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }
        }
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)


Rya*_*mon 5

我知道这已经有一个可接受的答案,但该解决方案没有考虑到我遇到的用例。

我特别需要一个仍然可点击的标题项,但禁用了 RecyclerView 的滚动机制。这可以通过以下代码完成:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                            @Override
     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
         return e.getAction() == MotionEvent.ACTION_MOVE;
     }

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

     }

     @Override
     public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
});
Run Code Online (Sandbox Code Playgroud)


I'm*_*gon 5

编写了Kotlin版本:

class NoScrollLinearLayoutManager(context: Context?) : LinearLayoutManager(context) {
    private var scrollable = true

    fun enableScrolling() {
        scrollable = true
    }

    fun disableScrolling() {
        scrollable = false
    }

    override fun canScrollVertically() =
            super.canScrollVertically() && scrollable


    override fun canScrollHorizontally() =
            super.canScrollVertically()

 && scrollable
}
Run Code Online (Sandbox Code Playgroud)

用法:

recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
Run Code Online (Sandbox Code Playgroud)