如何禁用RecyclerView滚动?

时间:2015-05-29 13:37:37

标签: android scroll android-recyclerview

我无法在(transaction_Id,tsh_id)中禁用滚动功能。我试着打电话给LIMIT,但我仍然可以滚动。

如何禁用滚动?

30 个答案:

答案 0 :(得分:306)

您应该覆盖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;
 }
};

答案 1 :(得分:110)

真正的答案是

recyclerView.setNestedScrollingEnabled(false);

documentation

中的更多信息

答案 2 :(得分:41)

这有点hackish解决方法,但它的工作原理;您可以在RecyclerView

中启用/禁用滚动功能

这是一个空的rv.setEnabled(false)窃取每个触摸事件,从而禁用目标RecyclerView

RecyclerView.OnItemTouchListener

使用它:

RecyclerView

答案 3 :(得分:30)

对于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">

答案 4 :(得分:29)

这对我有用:

/* numsec = number of seconds per instance */
#define numsec 3
time_t lasttime, thistime;
int i;
    lasttime = time(NULL);
    for(i = 0; i < 5; i++){     /* any loop here */
        while(1){
            thistime = time(NULL);
            if(thistime - lasttime >= numsec)
                break;
            if(thistime - lasttime >= 2)
                sleep(thistime - lasttime - 1);
        }
        /* run periodic code here */
        /* ... */
        lasttime += numsec;     /* update lasttime */
    }

答案 5 :(得分:8)

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

要冻结: recyclerView.setLayoutFrozen(true)

要取消冻结:recyclerView.setLayoutFrozen(false)

答案 6 :(得分:8)

如果仅禁用RecyclerView仅滚动功能,则可以使用setLayoutFrozen(true);的{​​{1}}方法。但这不能禁用触摸事件。

RecyclerView

答案 7 :(得分:8)

创建扩展 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();
}
}

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

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

  <com.yourpackage.xyx.NonscrollRecylerview 
 ...
 ... >

 ...
 ...

</com.yourpackage.xyz.NonscrollRecylerview >

答案 8 :(得分:5)

另一种选择是setLayoutFrozen,但它带来了许多其他副作用。

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#setLayoutFrozen(boolean)

答案 9 :(得分:5)

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

答案 10 :(得分:4)

扩展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);
          }
        }
      }
    });
  }

答案 11 :(得分:3)

我知道这已经有了一个公认的答案,但解决方案并没有考虑到我遇到的用例。

我特别需要一个仍然可点击的标题项,但却禁用了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) {

                    }
                });

答案 12 :(得分:3)

写了一个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
}

用法:

recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()

答案 13 :(得分:2)

覆盖onTouchEvent()和onInterceptTouchEvent(),如果根本不需要OnItemTouchListener,则返回false。 这不会禁用ViewHolders的OnClickListeners。

public class ScrollDisabledRecyclerView extends RecyclerView {
    public ScrollDisabledRecyclerView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }
}

答案 14 :(得分:2)

在活动的onCreate方法中,您可以简单地执行以下操作:

recyclerView.stopScroll()

它停止滚动。

答案 15 :(得分:2)

XML中的

: -

您可以添加

function setFieldDisabled() { var optionset = Xrm.Page.getAttribute("abs_tipodecuenta").getValue(); if (optionset == null) { Xrm.Page.getAttribute("abs_tipodecuenta").setValue(100000000); Xrm.Page.getControl("abs_tipodecuenta").setDisabled(true); } if (Xrm.Page.getAttribute("abs_tipodecuenta").getText() == 'Clientes' || Xrm.Page.getAttribute("abs_tipodecuenta").getText() == 'Agencias' || Xrm.Page.getAttribute("abs_tipodecuenta").getText() == 'Distribuidores') { disableFormFields(); } else { enableFormFields(); Xrm.Page.getControl("abs_tipodecuenta").setDisabled(true); } } function disableFormFields() { Xrm.Page.ui.controls.forEach(function (control, index) { var controlType = control.getControlType(); if (controlType != 'iframe' && controlType != 'webresource' && controlType != 'subgrid') { control.setDisabled(true); } }); } function enableFormFields() { Xrm.Page.ui.controls.forEach(function (control, index) { var controlType = control.getControlType(); if (controlType != 'iframe' && controlType != 'webresource' && controlType != 'subgrid') { control.setDisabled(false); } }); }

在子RecyclerView布局XML文件

Java中的

: -

window.onbeforeunload

使用Java代码中的RecyclerView。

使用ViewCompat(Java): -

window.onbeforeunload = function() { $('#box').remove(); }; 仅适用于 android_version&gt; 21 设备。要在所有设备上工作,请使用以下

android:nestedScrollingEnabled="false"

答案 16 :(得分:2)

出于某种原因@Alejandro Gracia的答案仅在几秒钟后开始工作。 我找到了一个瞬间阻止RecyclerView的解决方案:

#include <iostream>

template <typename T>
struct B { };

template <typename T>
struct D : B<T> {
    D(T );
};

template <typename T>
D<T>::D(T )
    : B<T>()
{
    std::cout << "def\n";
}

template <>
D<long>::D(long ) 
    : B<long>()
{
    std::cout << "hi\n";
}

int main()
{
    D<int> i(4);  // prints def
    D<long> l(5); // prints hi
}

答案 17 :(得分:1)

我在这个问题上苦苦挣扎了一个小时, 所以我想分享一下我的经历, 对于layoutManager解决方案,它很好,但如果你想reEnable滚动,回收器将返回顶部。

迄今为止最好的解决方案(至少对我而言)是使用@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);

答案 18 :(得分:1)

对于那些只希望阻止用户滚动RecyclerView而不松动smoothScrollToPosition或任何其他“定位”方法的人,我建议您扩展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;
                }
            }

答案 19 :(得分:1)

您应该添加以下行:

recyclerView.suppressLayout(true)

答案 20 :(得分:1)

您可以在设置适配器后添加此行

ViewCompat.setNestedScrollingEnabled(recyclerView, false);

现在,您的recyclerview可以平滑滚动了

答案 21 :(得分:1)

有一个非常简单的答案。

LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
                @Override
                public boolean canScrollVertically() {
                    return false;
                }
            };

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

答案 22 :(得分:0)

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

if(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;
            }
        });
    }

答案 23 :(得分:0)

您可以创建一个扩展 Recycler View 类的 Non Scrollable Recycler View,如下所示:

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;

public class NonScrollRecyclerView extends RecyclerView {

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

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

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

    @Override
    protected void onMeasure(int widthMeasure, int heightMeasure) {
        int heightMeasureCustom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasure, heightMeasureCustom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

答案 24 :(得分:0)

不推荐使用setLayoutFrozen,可以使用suppressLayout通过冻结RecyclerView来禁用滚动。

要冻结:

recyclerView.suppressLayout(true)

要取消冻结:

recyclerView.suppressLayout(false)

答案 25 :(得分:0)

有一种更简单的方法来禁用滚动(从技术上讲,它是拦截滚动事件并在满足条件时结束滚动事件),仅使用标准功能即可。 RecyclerView具有称为addOnScrollListener(OnScrollListener listener)的方法,仅使用此方法就可以阻止其滚动,就像这样:

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

用例: 假设您要在单击RecyclerView中的一项时禁用滚动,以便可以执行一些操作,而不会因意外滚动到另一项而分心,当您完成操作时,只需再次单击该项目以启用滚动。为此,您需要将OnClickListener附加到RecyclerView中的每个项目上,因此,当您单击某个项目时,会将isItemSelectedfalse切换到{{1} }。这样,当您尝试滚动时,true将自动调用方法RecyclerView,并且由于onScrollStateChanged设置为isItemSelected,因此它将在true到达之前立即停止。机会,很好...滚动。

注意:为获得更好的可用性,请尝试使用RecyclerView而非GestureListener来防止OnClickListener的点击。

答案 26 :(得分:0)

添加

android:descendantFocusability="blocksDescendants"

在您的孩子的SrollView或NestedScrollView(以及ListView的父级,recyclerview和gridview任何一个)

答案 27 :(得分:0)

只需将其添加到xml

中的recycleview即可
 android:nestedScrollingEnabled="false"
像这样

<android.support.v7.widget.RecyclerView
                    android:background="#ffffff"
                    android:id="@+id/myrecycle"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:nestedScrollingEnabled="false">

答案 28 :(得分:0)

遇到了一个包含多个RecycleView的片段,所以我在每个RecycleView中只需要一个滚动条而不是一个滚动条。

所以我只是将ScrollView放在包含2个RecycleViews的父容器中,并在RecycleView中使用android:isScrollContainer="false"

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutManager="LinearLayoutManager"
    android:isScrollContainer="false" />

答案 29 :(得分:0)

以下是我使用数据绑定的方法:

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false"
                android:onTouch="@{(v,e) -> true}"/>

取代&#34; true&#34;我使用了一个根据条件更改的布尔变量,以便回收器视图在禁用和启用之间切换。