wake-up-neo.com

Wie verwende ich RecyclerView in NestedScrollView?

Verwendung von RecyclerView in NestedScrollView? RecyclerView Inhalt ist nach dem Einstellen des Adapters nicht sichtbar.

UPDATELayoutcode aktualisiert.

<Android.support.v4.widget.NestedScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:padding="@dimen/keyline_1">

    </RelativeLayout>

    <View
        Android:id="@+id/separator"
        Android:layout_width="match_parent"
        Android:layout_height="1dp"
        Android:background="#e5e5e5" />

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/conversation"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

</LinearLayout>

</Android.support.v4.widget.NestedScrollView>
166
Mecid

Ersetzen Sie Ihre RecyclerView durch 

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/conversation"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content" />

hier, 

app:layout_behavior="@string/appbar_scrolling_view_behavior"

wird den Rest der Dinge schaffen. 

Eine weitere Sache: Sie müssen Ihre RecyclerView nicht in NestedScrollView einfügen

177
Rahul Upadhyay

UPDATE 1

Seit der Android Support Library 23.2.0 wurde die Methode setAutoMeasureEnabled(true) für LayoutManager hinzugefügt. RecyclerView wird so verpackt, dass es den Inhalt einwickelt und wie ein Zauber wirkt.
http://Android-developers.blogspot.ru/2016/02/Android-support-library-232.html

Also einfach so etwas hinzufügen:

    LayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setAutoMeasureEnabled(true);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setNestedScrollingEnabled(false);


UPDATE 2

Da 27.1.0 setAutoMeasureEnabled veraltet ist, sollten Sie die benutzerdefinierte Implementierung von LayoutManager mit der überschriebenen Methode isAutoMeasureEnabled() bereitstellen.

Nach vielen Anwendungsfällen von RecyclerView empfehle ich jedoch dringend, es nicht in Wrapping-Modus zu verwenden, da dies nicht beabsichtigt ist. Versuchen Sie, das gesamte Layout mit normalen Einzel-RecyclerView-Elementen mit verschiedenen Elementtypen zu überarbeiten. Oder verwenden Sie eine Methode mit LinearLayout, die ich als letztes Mittel beschrieben habe


Alte Antwort (nicht empfohlen)

Sie können RecyclerView innerhalb von NestedScrollView..__ verwenden. Zuerst sollten Sie Ihre eigene benutzerdefinierte LinearLayoutManager implementieren. Dadurch wird Ihre RecyclerView zum Umschließen des Inhalts verwendet. Zum Beispiel:

public class WrappingLinearLayoutManager extends LinearLayoutManager
{

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

    private int[] mMeasuredDimension = new int[2];

    @Override
    public boolean canScrollVertically() {
        return false;
    }

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
            int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);

        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);

        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            if (getOrientation() == HORIZONTAL) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        heightSpec,
                        mMeasuredDimension);

                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                measureScrapChild(recycler, i,
                        widthSpec,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);

                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }

        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
            int heightSpec, int[] measuredDimension) {

        View view = recycler.getViewForPosition(position);
        if (view.getVisibility() == View.GONE) {
            measuredDimension[0] = 0;
            measuredDimension[1] = 0;
            return;
        }
        // For adding Item Decor Insets to view
        super.measureChildWithMargins(view, 0, 0);
        RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
        int childWidthSpec = ViewGroup.getChildMeasureSpec(
                widthSpec,
                getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
                p.width);
        int childHeightSpec = ViewGroup.getChildMeasureSpec(
                heightSpec,
                getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
                p.height);
        view.measure(childWidthSpec, childHeightSpec);

        // Get decorated measurements
        measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
        measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
        recycler.recycleView(view);
    }
}

Verwenden Sie danach diese LayoutManager für Ihre RecyclerView

recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));

Sie sollten jedoch auch diese beiden Methoden aufrufen:

recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);

Hier setNestedScrollingEnabled(false) deaktivieren Sie das Scrollen für RecyclerView, damit das Scrolling-Ereignis von NestedScrollView nicht abgefangen wird. Und setHasFixedSize(false) bestimmt, dass Änderungen am Adapterinhalt die Größe der RecyclerView ändern können.

Wichtiger Hinweis: Diese Lösung ist in einigen Fällen ein wenig fehlerhaft und hat Probleme mit der Leistung. Wenn Sie also viele Elemente in Ihrer RecyclerView haben, würde ich empfehlen, die benutzerdefinierte LinearLayout- basierte Implementierung der Listenansicht zu verwenden Adapter dafür und verhalten Sie sich wie ListView oder RecyclerView

110
smbd uknow

1) Sie müssen die Unterstützungsbibliothek 23.2.0 (oder) oben verwenden

2) und RecyclerView height sind wrap_content.

3) recyclerView.setNestedScrollingEnabled(false)

Auf diese Weise funktioniert das Recycler-Muster jedoch nicht. (Das heißt, alle Ansichten werden auf einmal geladen, da wrap_content die Höhe des vollständigen RecyclerView benötigt, sodass alle untergeordneten Views auf einmal gezeichnet werden. Keine Ansicht wird wiederverwendet). Verwenden Sie dieses Muster nur, wenn es wirklich erforderlich ist. Versuchen Sie, viewType zu verwenden, und fügen Sie alle anderen Ansichten hinzu, die zu RecyclerView scrollen müssen, anstatt RecyclerView in Scrollview zu verwenden. Die Auswirkungen auf die Leistung werden sehr hoch sein.

Um es einfach zu machen: "Es fungiert nur als LinearLayout mit allen untergeordneten Ansichten."

91
Ashok Varma

Sie können Android:fillViewport="true" verwenden, um NestedScrollView das RecyclerView messen zu lassen. RecyclerView füllt die verbleibende Höhe. Wenn Sie also die NestScrollView scrollen möchten, können Sie die RecyclerView der minHeight einstellen.

33
zayn

Einfach das Hinzufügen von recyclerView.setNestedScrollingEnabled(false); vor setAdapter für mich funktionierte. Ich habe an keiner Stelle app:layout_behavior="@string/appbar_scrolling_view_behavior" hinzugefügt und keinen benutzerdefinierten Layout-Manager festgelegt

<Android.support.v4.widget.NestedScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="@color/white"
        Android:orientation="vertical">

        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_marginLeft="15dp"
            Android:layout_marginRight="15dp"
            Android:orientation="vertical">

            <TextView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:textColor="@color/white"
                Android:text="Some Text..."
                Android:padding="15dp" />

        </LinearLayout>

        <LinearLayout
            Android:orientation="vertical"
            Android:padding="15dp"
            Android:layout_marginTop="10dp"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

            <TextView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:text="Quick Links"
                Android:textColor="@color/black"
                Android:textStyle="bold"
                Android:textAllCaps="true"
                Android:paddingLeft="20dp"
                Android:drawableLeft="@drawable/ic_trending_up_black_24dp"
                Android:drawablePadding="10dp"
                Android:layout_marginBottom="10dp"
                Android:textSize="16sp"/>

            <View
                Android:layout_width="fill_parent"
                Android:layout_height="1dp"
                Android:background="#efefef"/>

            <Android.support.v7.widget.RecyclerView xmlns:Android="http://schemas.Android.com/apk/res/Android"
                Android:id="@+id/recyclerview"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent" />
        </LinearLayout>

    </LinearLayout>

</Android.support.v4.widget.NestedScrollView>
25
Vignesh Sundar

Das ist was für mich arbeiten

<Android.support.v4.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/rv_recycler_view"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</Android.support.v4.widget.NestedScrollView>
19
Ness Tyagi

Versuchen Sie, diese Bibliothek zu verwenden - https://github.com/serso/Android-linear-layout-manager .

Der LayoutManager der Bibliothek lässt RecyclerView seinen Inhalt einschließen. In diesem Fall ist RecyclerView "so groß wie innere Ansichten", dass es keine Bildlaufleisten gibt und der Benutzer die Bildlauffunktionen von NestedScrollView verwendet. Daher ist es nicht mehrdeutig wie "scrollbar in scrollbar".

7
alcsan

Es gibt einen einfachen und testenden Code, den Sie überprüfen können

<Android.support.v4.widget.NestedScrollView
     Android:layout_width="match_parent"
     Android:layout_height="match_parent"
     Android:fillViewport="true"
     app:layout_behavior="@string/appbar_scrolling_view_behavior">
    <Android.support.v7.widget.RecyclerView
           Android:layout_width="match_parent"
           Android:layout_height="match_parent"/>
   </Android.support.v4.widget.NestedScrollView>
7
Hakim Khan

Ich habe RecyclerView in einem NestedScrollView verwendet und es hat für mich funktioniert. Das einzige Problem, an das ich denken musste, war, dass ein NestedScrollView nur eine untergeordnete Ansicht hat. In meinem Fall verwendete ich die LienearLayout-Ansichtsgruppe, in der sich mein RecyclerView befand, sowie einige andere Ansichten, die ich brauchte.

Ich habe ein Problem, bei dem ich meine RecyclerView in die NestedScrollView stecke. Mir wurde klar, dass das Scrollen des Inhalts meines RecyclerView nachlässt. 

Später erkannte ich, dass mein RecyclerView das Scrolling-Ereignis empfing und daher mit dem Scrollverhalten der NestedScrollView in Konflikt stand. 

Um dieses Problem zu lösen, musste ich die Scroll-Funktionalität meines RecyclerView mit dieser Methode deaktivieren. movieListNewRecyclerView.setNestedScrollingEnabled(false);

Sie können mein Instagram für ein kurzes Video von mir überprüfen. Dies ist mein Instagram-Handle ofelix03

Klicke auf dieses Bild, um zu sehen, was ich getan habe

6
Felix Otoo

Hier der Code, den ich verwende, um Bildlaufprobleme zu vermeiden:

mRecyclerView = (RecyclerView) view.findViewById(Android.R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setHasFixedSize(false);
6
Anton Tananaev

Ich habe Viewpager und RecyclerView in der NestedScrollView. Nach dem Hinzufügen von Zeilen

recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);

Ich habe das Problem des langsamen Bildlaufs und des Nachlaufs gelöst.

4
Isham

Wenn Sie RecyclerView-23.2.1 oder höher verwenden. Folgende Lösung wird gut funktionieren: 

Fügen Sie in Ihrem Layout RecyclerView folgendermaßen hinzu:

<Android.support.v7.widget.RecyclerView
        Android:id="@+id/review_list"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:scrollbars="vertical" />

Und in deiner Java-Datei:

RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
layoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(new YourListAdapter(getContext()));

Hier wird layoutManager.setAutoMeasureEnabled(true); den Trick tun. 

Check out this issue und this developer blog für weitere Informationen.

3
abhilvare

Sie können eine Recycler-Ansicht nicht in einer verschachtelten Bildlaufansicht verwenden. Es ist nicht vorgesehen, weitere scrollbare Ansichten zu enthalten, da es sich jedoch um ein untergeordnetes Element eines Scroll-Layouts handelt, benötigen Sie die verschachtelte Scroll-Ansicht. Ich hatte das gleiche Problem, aber am Ende habe ich meine Textansicht verschoben, um eine Übersicht innerhalb der Recyclingübersicht zu sein, die Recyclingansicht zu einem direkten Kind des Koordinatorlayouts gemacht und die verschachtelte Scrollansicht gelöscht. Dann waren alle meine Probleme weg.

3
Barry Irvine

Es gibt viele gute Antworten. Der Schlüssel ist, dass Sie nestedScrollingEnabled auf false setzen müssen. Wie oben erwähnt, können Sie dies in Java-Code tun:

mRecyclerView.setNestedScrollingEnabled(false);

Sie haben aber auch die Möglichkeit, dieselbe Eigenschaft im XML-Code (Android:nestedScrollingEnabled="false") festzulegen:

 <Android.support.v7.widget.RecyclerView
 Android:id="@+id/recyclerview"
 Android:nestedScrollingEnabled="false"
 Android:layout_width="match_parent"
 Android:layout_height="match_parent" />
1
Alex Misulya

Für androidx heißt es androidx.core.widget.NestedScrollView - und scrollt auch wie Butter mit aktivierten Eigenschaften isScrollContainer und measureAllChildren:

<!-- Scrolling Content -->
<androidx.core.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:isScrollContainer="true"
    Android:measureAllChildren="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <androidx.recyclerview.widget.RecyclerView
        Android:id="@+id/recyclerview"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fastScrollEnabled="true"
        Android:scrollbarStyle="insideInset"
        Android:scrollbars="vertical"
        Android:splitMotionEvents="false"
        Android:verticalScrollbarPosition="right"/>

</androidx.core.widget.NestedScrollView>
1
Martin Zeitler

Ich musste CoordinatorLayout mit dem Scrollen in der Symbolleiste implementieren, und es dauerte nur den ganzen Tag, um dieses Problem zu lösen. Ich habe es geschafft, NestedScrollView überhaupt zu entfernen. Also verwende ich RelativeLayout nur an der Wurzel.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/rv_nearby"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</RelativeLayout>
1
Bogdan Ustyak

verwenden Sie recyclerView nicht in NestedScrollView. Dies kann zu Kaskadenproblemen führen! Ich schlage vor, ItemViewTypes in RecyclerView zu verwenden, um mehrere Arten von Ansichten zu verarbeiten. Fügen Sie einfach eine RecyclerView mit übereinstimmender Breite und Höhe hinzu. Überschreiben Sie dann in Ihrem recyclerViewAdapter getItemViewType und verwenden Sie position, um zu bestimmen, welches Layout aufgeblasen werden soll. Danach können Sie Ihren Ansichtsinhaber mit der onBindViewHolder-Methode bearbeiten.

0
Hossein Karami

Wenn Sie RecyclerView ScrollListener innerhalb NestedScrollView verwenden, funktioniert der Listener addOnScrollListener nicht ordnungsgemäß, wenn Sie beide verwenden.

Verwenden Sie diesen Code.

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

dieser Code funktioniert einwandfrei RecyclerView ScrollListener innerhalb NestedScrollView.

vielen Dank

0
Rahul

Eine Lösung, um die Recyclingfunktion des Recyclingberichts beizubehalten und zu vermeiden, dass der Recyclingbericht alle Ihre Daten lädt, ist das Festlegen einer festen Höhe im Recyclingbericht. Auf diese Weise ist der Recycling-Bereich nur auf die Last begrenzt, deren Höhe dem Benutzer anzeigen kann, dass er sein Element wiederverwendet, wenn Sie nach oben/unten scrollen.

0
BradlyMan