it-roy-ru.com

Как отключить прокрутку RecyclerView?

Я не могу отключить прокрутку в RecyclerView. Я попытался вызвать rv.setEnabled(false), но я все еще могу прокрутить.

Как я могу отключить прокрутку?

145
Zsolt Safrany

Для этого вам следует переопределить макет менеджера вашего повторного просмотра. Таким образом, он только отключит прокрутку, ни одну из других функций. Вы по-прежнему сможете обрабатывать нажатия или любые другие события касания. Например:-

Оригинал:

 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;
 }
};
292
Saurabh Garg

Настоящий ответ 

recyclerView.setNestedScrollingEnabled(false);

Больше информации в документация

106
Bozic Nebojsa

Это немного хакерский обходной путь, но он работает; Вы можете включить/отключить прокрутку в 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 
41
Zsolt Safrany

Для 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">
27
Milad Faridnia

Это работает для меня: 

  recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
27
alxgarcia

Создать класс, который расширяет RecyclerView class

    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
Ashish

Если вы просто отключите только функцию прокрутки of RecyclerView, тогда вы можете использовать setLayoutFrozen(true); метод RecyclerView. Но нельзя отключить сенсорное событие.

your_recyclerView.setLayoutFrozen(true);
6
Ekta Bhawsar

Другой альтернативой является setLayoutFrozen, но он сопровождается множеством других побочных эффектов.

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

5
Taig

Вы можете отключить прокрутку, заморозив RecyclerView.

Чтобы заморозить: recyclerView.setLayoutFrozen(true)

Разморозить: recyclerView.setLayoutFrozen(false)

4
Virat Singh

Расширьте 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);
          }
        }
      }
    });
  }
4
Aidanvii
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            // Stop only scrolling.
            return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
        }
    });

3
rajesh

Я знаю, что на это уже есть принятый ответ, но решение не учитывает вариант использования, с которым я столкнулся.

Мне особенно нужен был элемент заголовка, который можно было нажимать, но при этом отключил механизм прокрутки в 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) {

                    }
                });
3
Ryan Simon

Написал котлинскую версию:

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()
3
I'm a frog dragon

Переопределите onTouchEvent () и onInterceptTouchEvent () и верните false, если вам вообще не нужен OnItemTouchListener . Это не отключает OnClickListeners ViewHolders.

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;
    }
}
2
ypresto

По какой-то причине ответ @Alejandro Gracia начинает работать только через несколько секунд .. Я нашел решение, которое мгновенно блокирует RecyclerView:

recyclerView.addOnItemTouchListener(new 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) {
            }
        });
2
vovahost

в XML: -

Можете добавить

Android:nestedScrollingEnabled="false" 

в дочернем XML-файле макета RecyclerView

или же

в Java: -

childRecyclerView.setNestedScrollingEnabled(false);

к вашему RecyclerView в коде Java.

Использование ViewCompat (Java): -

childRecyclerView.setNestedScrollingEnabled(false); будет работать только на Android_version> 21 устройствах. для работы на всех устройствах используйте следующее

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);

2
jafarbtech

Я боролся с этой проблемой в течение часа, Поэтому я хотел бы поделиться своим опытом, Для решения layoutManager это хорошо, но если вы захотите включить прокрутку, то вернитесь к началу.

Лучшее решение (пока, по крайней мере, для меня) - это использование метода @Zsolt Safrany, но с добавлением геттера и сеттера, чтобы вам не пришлось удалять или добавлять 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);
1
Aladdin

Столкнулся с фрагментом, который содержит несколько RecycleView, поэтому мне нужна только одна полоса прокрутки вместо одной полосы прокрутки в каждом RecycleView.

Поэтому я просто помещаю ScrollView в родительский контейнер, который содержит 2 RecycleViews, и использую Android:isScrollContainer="false" в RecycleView.

<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" />
0
pk028382

Существует более простой способ отключить прокрутку, используя только стандартные функции. У 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, поэтому при нажатии на элемент он переключит isItemSelected с false на true. Таким образом, при попытке прокрутки RecyclerView автоматически вызовет метод onScrollStateChanged, а поскольку для isItemSelected установлено значение true, он немедленно остановится, прежде чем RecyclerView получит возможность, ну ... прокручивать.

Примечание: для удобства использования попробуйте использовать GestureListener вместо OnClickListener для предотвращения кликов accidental.

0
Tim Jorjev

Вы можете добавить эту строку после настройки вашего адаптера

ViewCompat.setNestedScrollingEnabled(recyclerView, false);

Теперь ваш переработчик будет работать с плавной прокруткой

0
Atefeh Srch

Вот как я это сделал с привязкой данных:

            <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}"/>

Вместо «true» я использовал логическую переменную, которая изменялась в зависимости от условия, чтобы представление рециркулятора переключалось между отключением и включением.

0
bwhite

Просто добавьте это в свой recycleview в xml

 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">
0
anas

Есть действительно простой ответ.

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

Приведенный выше код отключает вертикальную прокрутку RecyclerView.

0
Emi Raz

Добавлять

Android:descendantFocusability="blocksDescendants"

в вашем потомке SrollView или NestedScrollView (и родительский элемент ListView, recyclerview и gridview любой)

0
Pankaj Talaviya