Wie kann RecyclerView Scrollen deaktiviert werden?

Ich kann das Scrollen im RecyclerView nicht deaktivieren. Ich habe versucht, rv.setEnabled(false) aber ich kann noch scrollen.

Wie kann ich das Scrollen deaktivieren?

Sie sollten den Layoutmanager Ihres Recyclingview dafür überschreiben. Auf diese Weise wird nur das Scrollen deaktiviert, keine der anderen functionen. Sie können weiterhin mit Klick- oder anderen Berührungsereignissen umgehen. Beispielsweise:-

Original:

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

Hier können Sie mit dem Flag “isScrollEnabled” die Scroll-functionalität Ihrer Recycle-Ansicht temporär aktivieren / deaktivieren.

Ebenfalls:

Überschreiben Sie einfach Ihre vorhandene Implementierung, um das Scrollen zu deaktivieren und Klicken zuzulassen.

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

Die wirkliche Antwort ist

 recyclerView.setNestedScrollingEnabled(false); 

Weitere Informationen in der Dokumentation

Dies ist ein bisschen hackish Workaround, aber es funktioniert; Sie können Scrollen im RecyclerView aktivieren / deaktivieren.

Dies ist ein leerer RecyclerView.OnItemTouchListener , der jedes Berührungsereignis stiehlt und somit das Ziel RecyclerView deaktiviert.

 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) { } } 

Es benutzen:

 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 

Das funktioniert für mich:

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

Für API 21 und höher:

Kein Java-Code erforderlich. Du kannst android:nestedScrollingEnabled="false" in xml setzen:

  

Erstellen Sie eine class, die die RecyclerView- class erweitert

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

Dadurch wird das Bildlaufereignis, nicht jedoch die Klickereignisse deaktiviert

Verwenden Sie dies in Ihrem XML-Code wie folgt:

   ... ...  

Erweitern Sie den LayoutManager und überschreiben Sie canScrollHorizontally() und canScrollVertically() , um das Scrollen zu deaktivieren.

Beachten Sie, dass das Einfügen von Elementen am Anfang nicht automatisch zum Anfang zurück blättert. Um dies zu umgehen, tun Sie Folgendes:

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

Eine andere Alternative ist setLayoutFrozen , aber es kommt mit einer Reihe von anderen Nebenwirkungen.

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

Ich weiß, dass dies bereits eine akzeptierte Antwort hat, aber die Lösung berücksichtigt keinen Anwendungsfall, auf den ich gestoßen bin.

Ich brauchte speziell einen Header-Artikel, der immer noch anklickbar war, aber den Scroll-Mechanismus des RecyclerView deaktiviert. Dies kann mit dem folgenden Code erreicht werden:

 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) { } }); 
 recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { // Stop only scrolling. return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING; } }); 

Aus irgendeinem Grund @Alejandro Gracia Antwort beginnt erst nach ein paar Sekunden zu arbeiten. Ich habe eine Lösung gefunden, die den RecyclerView sofort blockiert:

 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) { } }); 

Überschreiben Sie onTouchEvent () und onInterceptTouchEvent () und geben Sie false zurück, wenn Sie OnItemTouchListener überhaupt nicht benötigen. Dies deaktiviert OnClickListeners von ViewHolders nicht.

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

in XML: –

Du kannst hinzufügen

android:nestedScrollingEnabled="false"

in der Child RecyclerView Layout-XML-Datei

oder

in Java: –

childRecyclerView.setNestedScrollingEnabled(false);

zu Ihrem RecyclerView in Java-Code.

ViewCompat verwenden (Java): –

childRecyclerView.setNestedScrollingEnabled(false); funktioniert nur in android_version> 21 Geräten. in allen Geräten zu arbeiten, verwenden Sie Folgendes

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);

Wenn Sie nur die setLayoutFrozen(true); von RecyclerView deaktivieren, können Sie setLayoutFrozen(true); Methode von RecyclerView . Aber es kann nicht Touch-Event deaktivieren.

 your_recyclerView.setLayoutFrozen(true); 

Ich habe in dieser Angelegenheit für einige Stunden gekämpft, also möchte ich meine Erfahrung teilen, Für die layoutManager Lösung ist es in Ordnung, aber wenn Sie Scrolling reEnable wollen, wird der Recycler wieder nach oben.

Die beste Lösung bisher (zumindest für mich) ist die Verwendung von @Zsolt Safrany Methode, aber Hinzufügen von Getter und Setter, so dass Sie den OnItemTouchListener nicht entfernen oder hinzufügen müssen.

Wie folgt

 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){} } 

Verwendung

 RecyclerViewDisabler disabler = new RecyclerViewDisabler(true); feedsRecycler.addOnItemTouchListener(disabler); // TO ENABLE/DISABLE JUST USE THIS disabler.setEnable(enable); 

Schrieb eine Kotlin-Version:

 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 } 

Verwendung:

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

Hier ist, wie ich es mit Datenbindung gemacht habe:

   

Anstelle von “true” habe ich eine boolesche Variable verwendet, die sich basierend auf einer Bedingung geändert hat, sodass die Recycleransicht zwischen deaktiviert und aktiviert umgeschaltet wurde.

Kam mit einem Fragment, das mehrere RecycleView enthält, so dass ich nur eine Bildlaufleiste anstelle einer Bildlaufleiste in jedem RecycleView benötige.

Also lege ich die ScrollView in den übergeordneten Container, der die 2 RecycleViews enthält, und benutze android:isScrollContainer="false" in der RecycleView

  

Fügen Sie das einfach zu Ihrem recycleview in XML hinzu

  android:nestedScrollingEnabled="false" 

so was

  

Hinzufügen

 android:descendantFocusability="blocksDescendants" 

in Ihrem Kind von SrollView oder NestedScrollView (und Eltern von ListView, Recyclerview und Gridview jeder)

Es gibt eine einfachere Möglichkeit, das Scrollen zu deaktivieren, indem Sie nur Standardfunktionen verwenden. RecyclerView hat die Methode namens addOnScrollListener(OnScrollListener listener) , und mit nur diesem können Sie verhindern, dass es addOnScrollListener(OnScrollListener listener) , nur so:

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

Anwendungsfall: Nehmen wir an, Sie möchten das Scrollen deaktivieren, wenn Sie auf eines der Elemente in RecyclerView klicken, damit Sie einige Aktionen ausführen können, ohne durch versehentliches Scrollen zu einem anderen Element abgelenkt zu werden. Wenn Sie damit fertig sind, klicken Sie einfach auf dem Objekt erneut, um das Scrollen zu ermöglichen. Dazu müssten Sie OnClickListener an jedes Element in RecyclerView anhängen. Wenn Sie also auf ein Element klicken, wird isItemSelected von false in true isItemSelected . Auf diese Weise ruft RecyclerView beim onScrollStateChanged automatisch die Methode onScrollStateChanged und da isItemSelected auf true , wird es sofort gestoppt, bevor RecyclerView die Chance bekommt, nun … scrollen zu können.

Hinweis: Verwenden GestureListener zur besseren Benutzerfreundlichkeit den GestureListener anstelle von OnClickListener , um accidental Klicks zu verhindern.