wake-up-neo.com

RecyclerView in ScrollView funktioniert nicht

Ich versuche, ein Layout zu implementieren, das RecyclerView und ScrollView im selben Layout enthält.

Layoutvorlage: 

<RelativeLayout>
    <ScrollView Android:id="@+id/myScrollView">
       <unrelated data>...</unrealated data>

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


</RelativeLayout>

Probleme: Ich kann bis zum letzten Element von ScrollView scrollen.

Dinge, die ich probiert habe: 

  1. kartenansicht in der ScrollView (jetzt ScrollView enthält RecyclerView) - kann die Karte bis zur RecyclerView sehen
  2. der erste Gedanke war, diese viewGroup mithilfe von RecyclerView anstelle von ScrollView zu implementieren, wobei einer der Sichttypen CardView ist, aber ich habe genau dieselben Ergebnisse wie mit ScrollView
204
royB

verwenden Sie NestedScrollView anstelle von ScrollView

Bitte gehen Sie durch NestedScrollView Referenzdokument für weitere Informationen.

und füge recyclerView.setNestedScrollingEnabled(false); zu deiner RecyclerView hinzu

496
Yang Peiyong

Ich weiß, ich bin zu spät dran, aber das Problem besteht auch noch, nachdem Google das Problem mit dem Android.support.v7.widget.RecyclerView Behoben hat.

Die Ausgabe, die ich jetzt erhalte, ist RecyclerView, wobei layout_height=wrap_content Nicht die Höhe aller in ScrollView ausgegebenen Elemente einnimmt, die nur tritt bei Marshmallow- und Nougat + -Versionen (API 23, 24, 25) auf.
(UPDATE: Ersetzen von ScrollView durch Android.support.v4.widget.NestedScrollView Funktioniert bei allen Versionen. Ich habe irgendwie das Testen verpasst akzeptierte Lösung . Hinzugefügt in meinem Github Projekt als Demo.)

Nachdem ich verschiedene Dinge ausprobiert habe, habe ich eine Problemumgehung gefunden, die dieses Problem behebt.

Hier ist meine Layoutstruktur auf den Punkt gebracht:

<ScrollView>
  <LinearLayout> (vertical - this is the only child of scrollview)
     <SomeViews>
     <RecyclerView> (layout_height=wrap_content)
     <SomeOtherViews>

Die Problemumgehung ist das Umbrechen des RecyclerView mit RelativeLayout. Fragen Sie mich nicht, wie ich diese Problemumgehung gefunden habe !!! ¯\_(ツ)_/¯

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:descendantFocusability="blocksDescendants">

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

</RelativeLayout>

Ein vollständiges Beispiel finden Sie in GitHub project - https://github.com/amardeshbd/Android-recycler-view-wrap-content

Hier ist ein Demo-Screencast, der das Update in Aktion zeigt:

Screencast

86
Hossain Khan

Obwohl die Empfehlung das 

sie sollten niemals eine scrollbare Ansicht in eine andere scrollbare Ansicht einfügen

Ist ein guter Ratschlag, wenn Sie jedoch eine feste Höhe in der Sicht des Recyclers einstellen, sollte dies einwandfrei funktionieren.

Wenn Sie die Höhe des Adapterelement-Layouts kennen, können Sie einfach die Höhe der RecyclerView berechnen.

int viewHeight = adapterItemSize * adapterData.size();
recyclerView.getLayoutParams().height = viewHeight;
51
Joakim Engstrom

Falls die Einstellung der festen Höhe für die RecyclerView für jemanden (wie ich) nicht funktioniert hat, habe ich Folgendes zur Lösung der festen Höhe hinzugefügt:

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        int action = e.getAction();
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                rv.getParent().requestDisallowInterceptTouchEvent(true);
                break;
        }
        return false;
    }

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

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
});
24
Clans

Die neue Android Support Library 23.2 löst dieses Problem. Sie können jetzt wrap_content als Höhe Ihrer RecyclerView einstellen und funktioniert ordnungsgemäß.

Android Support Library 23.2

23
kevings14

RecyclerViews können in ScrollViews eingefügt werden, solange sie nicht selbst scrollen. In diesem Fall ist es sinnvoll, eine feste Höhe festzulegen.

Die richtige Lösung ist, wrap_content auf der RecyclerView-Höhe zu verwenden und anschließend einen benutzerdefinierten LinearLayoutManager zu implementieren, der die Umwicklung richtig handhabt.

Kopieren Sie diesen LinearLayoutManager in Ihr Projekt: https://github.com/serso/Android-linear-layout-manager/blob/master/lib/src/main/Java/org/solovyev/Android/views/llm/LinearLayoutManager .Java

Dann wickeln Sie die RecyclerView ein:

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

Und stell es so auf:

    RecyclerView list = (RecyclerView)findViewById(R.id.list);
    list.setHasFixedSize(true);
    list.setLayoutManager(new com.example.myapp.LinearLayoutManager(list.getContext()));
    list.setAdapter(new MyViewAdapter(data));

Bearbeiten: Dies kann zu Komplikationen beim Scrollen führen, da RecyclerView die Berührungsereignisse von ScrollView stehlen kann. Meine Lösung bestand nur darin, die RecyclerView in allen Bereichen abzugrenzen und mit einem LinearLayout zu arbeiten, programmgesteuert die Unteransichten aufzublasen und sie dem Layout hinzuzufügen.

15
jcady

Für ScrollView können Sie fillViewport=true und layout_height="match_parent" wie folgt verwenden und die Recycler-Ansicht einfügen:

<ScrollView
    Android:fillViewport="true"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_below="@+id/llOptions">
          <Android.support.v7.widget.RecyclerView
            Android:id="@+id/rvList"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            />
</ScrollView>

Keine weitere Höheneinstellung durch Code erforderlich.

14
mustaq

Es ist nicht gut, die Höhe von RecyclerView manuell zu berechnen. Verwenden Sie eine benutzerdefinierte LayoutManager

Der Grund für das obige Problem ist, dass jede Ansicht, deren Scroll (ListView, GridView, RecyclerView) ihre Höhe hat, die Höhe nicht berechnet hat, wenn das Hinzufügen als untergeordnetes Element in einer anderen Ansicht einen Scroll hat. Durch Überschreiben der onMeasure-Methode wird das Problem gelöst.

Bitte ersetzen Sie den Standard-Layout-Manager durch den folgenden:

public class MyLinearLayoutManager extends Android.support.v7.widget.LinearLayoutManager {

private static boolean canMakeInsetsDirty = true;
private static Field insetsDirtyField = null;

private static final int CHILD_WIDTH = 0;
private static final int CHILD_HEIGHT = 1;
private static final int DEFAULT_CHILD_SIZE = 100;

private final int[] childDimensions = new int[2];
private final RecyclerView view;

private int childSize = DEFAULT_CHILD_SIZE;
private boolean hasChildSize;
private int overScrollMode = ViewCompat.OVER_SCROLL_ALWAYS;
private final Rect tmpRect = new Rect();

@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(Context context) {
    super(context);
    this.view = null;
}

@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
    this.view = null;
}

@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(RecyclerView view) {
    super(view.getContext());
    this.view = view;
    this.overScrollMode = ViewCompat.getOverScrollMode(view);
}

@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(RecyclerView view, int orientation, boolean reverseLayout) {
    super(view.getContext(), orientation, reverseLayout);
    this.view = view;
    this.overScrollMode = ViewCompat.getOverScrollMode(view);
}

public void setOverScrollMode(int overScrollMode) {
    if (overScrollMode < ViewCompat.OVER_SCROLL_ALWAYS || overScrollMode > ViewCompat.OVER_SCROLL_NEVER)
        throw new IllegalArgumentException("Unknown overscroll mode: " + overScrollMode);
    if (this.view == null) throw new IllegalStateException("view == null");
    this.overScrollMode = overScrollMode;
    ViewCompat.setOverScrollMode(view, overScrollMode);
}

public static int makeUnspecifiedSpec() {
    return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
}

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

    final boolean hasWidthSize = widthMode != View.MeasureSpec.UNSPECIFIED;
    final boolean hasHeightSize = heightMode != View.MeasureSpec.UNSPECIFIED;

    final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY;
    final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY;

    final int unspecified = makeUnspecifiedSpec();

    if (exactWidth && exactHeight) {
        // in case of exact calculations for both dimensions let's use default "onMeasure" implementation
        super.onMeasure(recycler, state, widthSpec, heightSpec);
        return;
    }

    final boolean vertical = getOrientation() == VERTICAL;

    initChildDimensions(widthSize, heightSize, vertical);

    int width = 0;
    int height = 0;

    // it's possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This
    // happens because their invalidation happens after "onMeasure" method. As a workaround let's clear the
    // recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never
    // called whiles scrolling)
    recycler.clear();

    final int stateItemCount = state.getItemCount();
    final int adapterItemCount = getItemCount();
    // adapter always contains actual data while state might contain old data (f.e. data before the animation is
    // done). As we want to measure the view with actual data we must use data from the adapter and not from  the
    // state
    for (int i = 0; i < adapterItemCount; i++) {
        if (vertical) {
            if (!hasChildSize) {
                if (i < stateItemCount) {
                    // we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
                    // we will use previously calculated dimensions
                    measureChild(recycler, i, widthSize, unspecified, childDimensions);
                } else {
                    logMeasureWarning(i);
                }
            }
            height += childDimensions[CHILD_HEIGHT];
            if (i == 0) {
                width = childDimensions[CHILD_WIDTH];
            }
            if (hasHeightSize && height >= heightSize) {
                break;
            }
        } else {
            if (!hasChildSize) {
                if (i < stateItemCount) {
                    // we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
                    // we will use previously calculated dimensions
                    measureChild(recycler, i, unspecified, heightSize, childDimensions);
                } else {
                    logMeasureWarning(i);
                }
            }
            width += childDimensions[CHILD_WIDTH];
            if (i == 0) {
                height = childDimensions[CHILD_HEIGHT];
            }
            if (hasWidthSize && width >= widthSize) {
                break;
            }
        }
    }

    if (exactWidth) {
        width = widthSize;
    } else {
        width += getPaddingLeft() + getPaddingRight();
        if (hasWidthSize) {
            width = Math.min(width, widthSize);
        }
    }

    if (exactHeight) {
        height = heightSize;
    } else {
        height += getPaddingTop() + getPaddingBottom();
        if (hasHeightSize) {
            height = Math.min(height, heightSize);
        }
    }

    setMeasuredDimension(width, height);

    if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) {
        final boolean fit = (vertical && (!hasHeightSize || height < heightSize))
                || (!vertical && (!hasWidthSize || width < widthSize));

        ViewCompat.setOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS);
    }
}

private void logMeasureWarning(int child) {
    if (BuildConfig.DEBUG) {
        Log.w("MyLinearLayoutManager", "Can't measure child #" + child + ", previously used dimensions will be reused." +
                "To remove this message either use #setChildSize() method or don't run RecyclerView animations");
    }
}

private void initChildDimensions(int width, int height, boolean vertical) {
    if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
        // already initialized, skipping
        return;
    }
    if (vertical) {
        childDimensions[CHILD_WIDTH] = width;
        childDimensions[CHILD_HEIGHT] = childSize;
    } else {
        childDimensions[CHILD_WIDTH] = childSize;
        childDimensions[CHILD_HEIGHT] = height;
    }
}

@Override
public void setOrientation(int orientation) {
    // might be called before the constructor of this class is called
    //noinspection ConstantConditions
    if (childDimensions != null) {
        if (getOrientation() != orientation) {
            childDimensions[CHILD_WIDTH] = 0;
            childDimensions[CHILD_HEIGHT] = 0;
        }
    }
    super.setOrientation(orientation);
}

public void clearChildSize() {
    hasChildSize = false;
    setChildSize(DEFAULT_CHILD_SIZE);
}

public void setChildSize(int childSize) {
    hasChildSize = true;
    if (this.childSize != childSize) {
        this.childSize = childSize;
        requestLayout();
    }
}

private void measureChild(RecyclerView.Recycler recycler, int position, int widthSize, int heightSize, int[] dimensions) {
    final View child;
    try {
        child = recycler.getViewForPosition(position);
    } catch (IndexOutOfBoundsException e) {
        if (BuildConfig.DEBUG) {
            Log.w("MyLinearLayoutManager", "MyLinearLayoutManager doesn't work well with animations. Consider switching them off", e);
        }
        return;
    }

    final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams();

    final int hPadding = getPaddingLeft() + getPaddingRight();
    final int vPadding = getPaddingTop() + getPaddingBottom();

    final int hMargin = p.leftMargin + p.rightMargin;
    final int vMargin = p.topMargin + p.bottomMargin;

    // we must make insets dirty in order calculateItemDecorationsForChild to work
    makeInsetsDirty(p);
    // this method should be called before any getXxxDecorationXxx() methods
    calculateItemDecorationsForChild(child, tmpRect);

    final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child);
    final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child);

    final int childWidthSpec = getChildMeasureSpec(widthSize, hPadding + hMargin + hDecoration, p.width, canScrollHorizontally());
    final int childHeightSpec = getChildMeasureSpec(heightSize, vPadding + vMargin + vDecoration, p.height, canScrollVertically());

    child.measure(childWidthSpec, childHeightSpec);

    dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin;
    dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin;

    // as view is recycled let's not keep old measured values
    makeInsetsDirty(p);
    recycler.recycleView(child);
}

private static void makeInsetsDirty(RecyclerView.LayoutParams p) {
    if (!canMakeInsetsDirty) {
        return;
    }
    try {
        if (insetsDirtyField == null) {
            insetsDirtyField = RecyclerView.LayoutParams.class.getDeclaredField("mInsetsDirty");
            insetsDirtyField.setAccessible(true);
        }
        insetsDirtyField.set(p, true);
    } catch (NoSuchFieldException e) {
        onMakeInsertDirtyFailed();
    } catch (IllegalAccessException e) {
        onMakeInsertDirtyFailed();
    }
}

private static void onMakeInsertDirtyFailed() {
    canMakeInsetsDirty = false;
    if (BuildConfig.DEBUG) {
        Log.w("MyLinearLayoutManager", "Can't make LayoutParams insets dirty, decorations measurements might be incorrect");
    }
}
}
13
Arun Antoney

Versuche dies. Antwort sehr spät. Aber in Zukunft sicherlich jedem helfen. 

Setze deinen Scrollview auf NestedScrollView

<Android.support.v4.widget.NestedScrollView>
 <Android.support.v7.widget.RecyclerView>
</Android.support.v7.widget.RecyclerView>
</Android.support.v4.widget.NestedScrollView>

In deinem Recyclerview  

recyclerView.setNestedScrollingEnabled(false); 
recyclerView.setHasFixedSize(false);
9
Ranjith Kumar

UPDATE: Diese Antwort ist veraltet, da es Widgets wie NestedScrollView und RecyclerView gibt, die verschachteltes Scrollen unterstützen.

sie sollten niemals eine scrollbare Ansicht in eine andere scrollbare Ansicht einfügen!

ich schlage vor, dass Sie Ihre Hauptlayout-Recycler-Ansicht erstellen und Ihre Ansichten als Elemente der Recycler-Ansicht einfügen.

schauen Sie sich dieses Beispiel an, in dem gezeigt wird, wie mehrere Ansichten innerhalb des Recycler-Ansichtsadapters verwendet werden. Link zum Beispiel

7
EC84B4

Wenn Sie RecyclerView in NestedScrollView eingeben und recyclerView.setNestedScrollingEnabled(false); aktivieren, wird beim Scrollen gut funktionieren.
Allerdings gibt es ein Problem

RecyclerViewrecycle nicht

Beispielsweise hat Ihr RecyclerView (in NestedScrollView oder ScrollView) 100 Elemente.
Wenn Activity gestartet wird, erstellt 100 item (onCreateViewHolder und onBindViewHolder von 100 item werden gleichzeitig aufgerufen).
Beispiel: Für jedes Element laden Sie ein großes Bild aus API => Aktivität erstellt -> 100 Bild wird geladen.
Es macht das Starten der Aktivität langsamer und verzögert sich.
Mögliche Lösung:
- Denken Sie darüber nach, RecyclerView mit mehreren Typen zu verwenden. 

Wenn es in Ihrem Fall jedoch nur ein paar Elemente in RecyclerView und recycle gibt, oder recycle die Leistung nicht stark beeinträchtigen, können Sie RecyclerView in ScrollView verwenden

5
Linh

Sie können diesen Weg entweder verwenden:

Fügen Sie diese Zeile zu Ihrer XML-Ansicht recycleerView hinzu:

        Android:nestedScrollingEnabled="false"

probieren Sie es aus, das Recycling wird mit flexibler Höhe problemlos gescrollt

hoffe das hat geholfen.

4
tahaDev

Ich hatte das gleiche Problem. Ich habe es versucht und es funktioniert. Ich teile mein XML- und Java-Code. Hoffe das hilft jemandem.

Hier ist die XML

<?xml version="1.0" encoding="utf-8"?>

 

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

        <ImageView
            Android:id="@+id/iv_thumbnail"
            Android:layout_width="match_parent"
            Android:layout_height="200dp" />

        <TextView
            Android:id="@+id/tv_description"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="Description" />

        <Button
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="Buy" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="Reviews" />
        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/rc_reviews"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

        </Android.support.v7.widget.RecyclerView>

    </LinearLayout>
</ScrollView>

Hier ist der zugehörige Java-Code. Es wirkt wie ein Zauber.

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setNestedScrollingEnabled(false);
2
Zeeshan Shabbir

Es scheint, dass NestedScrollView das Problem löst. Ich habe mit diesem Layout getestet:

<Android.support.v4.widget.NestedScrollView
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:id="@+id/activity_main"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
>

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

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@string/dummy_text"
        />

    <Android.support.v7.widget.CardView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="16dp"
        Android:layout_marginRight="16dp"
        >
        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recycler_view"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"/>

    </Android.support.v7.widget.CardView>

</LinearLayout>

Und es funktioniert ohne Probleme

2
royB

Das macht den Trick:

recyclerView.setNestedScrollingEnabled(false);
1
Shylendra Madda

Tatsächlich besteht der Hauptzweck der RecyclerView darin, ListView und ScrollView zu kompensieren. Anstatt das zu tun, was Sie tatsächlich tun: Wenn Sie eine RecyclerView in einer ScrollView haben, würde ich vorschlagen, nur eine RecyclerView zu haben, die viele Arten von Kindern verarbeiten kann.

0
Samer

Es tut uns leid, zu spät zur Party zu kommen, aber es scheint, als gäbe es eine andere Lösung, die perfekt für den von Ihnen erwähnten Fall funktioniert.

Wenn Sie eine Recycler-Ansicht in einer Recycler-Ansicht verwenden, scheint diese einwandfrei zu funktionieren. Ich habe es persönlich ausprobiert und verwendet, und es scheint, dass es keine Langsamkeit und keine Ruckeln gibt. Jetzt bin ich nicht sicher, ob dies eine bewährte Methode ist oder nicht, aber wenn mehrere Recycler-Ansichten verschachtelt werden, verlangsamt sich sogar die verschachtelte Bildlaufansicht. Das scheint aber gut zu funktionieren. Bitte probieren Sie es aus. Ich bin sicher, dass das Schachteln damit vollkommen in Ordnung sein wird.

0

Ich habe CustomLayoutManager verwendet, um RecyclerView Scrolling zu deaktivieren. __ Verwenden Sie auch Recycler View nicht als WrapContent, sondern als 0dp, Weight = 1

public class CustomLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled;

    // orientation should be LinearLayoutManager.VERTICAL or HORIZONTAL
    public CustomLayoutManager(Context context, int orientation, boolean isScrollEnabled) {
        super(context, orientation, false);
        this.isScrollEnabled = isScrollEnabled;
    }

    @Override
    public boolean canScrollVertically() {
        //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
        return isScrollEnabled && super.canScrollVertically();
    }
}

Verwenden Sie CustomLayoutManager in RecyclerView:

CustomLayoutManager mLayoutManager = new CustomLayoutManager(getBaseActivity(), CustomLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(mLayoutManager);
        ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); 
        recyclerView.setAdapter(statsAdapter);

XML der Benutzeroberfläche:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@drawable/background_main"
    Android:fillViewport="false">


    <LinearLayout
        Android:id="@+id/contParentLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <FrameLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

            <edu.aku.family_hifazat.libraries.mpchart.charts.PieChart
                Android:id="@+id/chart1"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_marginBottom="@dimen/x20dp"
                Android:minHeight="@dimen/x300dp">

            </edu.aku.family_hifazat.libraries.mpchart.charts.PieChart>


        </FrameLayout>

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recyclerView"
            Android:layout_width="match_parent"
            Android:layout_height="0dp"
            Android:layout_weight="1">


        </Android.support.v7.widget.RecyclerView>


    </LinearLayout>


</ScrollView>
0
Hamza Khan

Wenn RecyclerView nur eine Zeile in ScrollView anzeigt. Sie müssen nur die Höhe Ihrer Zeile auf Android:layout_height="wrap_content" setzen.

0
SANAT

sie können den LinearLayoutManager auch überschreiben, damit die Recyclingübersicht reibungslos läuft 

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

Zuerst sollten Sie NestedScrollView anstelle von ScrollView verwenden und die RecyclerView in NestedScrollView einfügen.

Verwenden Sie die benutzerdefinierte Layoutklasse, um die Höhe und Breite des Bildschirms zu messen:

public class CustomLinearLayoutManager extends LinearLayoutManager {

public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
}

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

@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(i, View.MeasureSpec.UNSPECIFIED),
                    heightSpec,
                    mMeasuredDimension);

            width = width + mMeasuredDimension[0];
            if (i == 0) {
                height = mMeasuredDimension[1];
            }
        } else {
            measureScrapChild(recycler, i,
                    widthSpec,
                    View.MeasureSpec.makeMeasureSpec(i, 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);
    recycler.bindViewToPosition(view, position);
    if (view != null) {
        RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
        int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                getPaddingLeft() + getPaddingRight(), p.width);
        int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                getPaddingTop() + getPaddingBottom(), p.height);
        view.measure(childWidthSpec, childHeightSpec);
        measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
        measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
        recycler.recycleView(view);
    }
}
}

Und implementiere den folgenden Code in die Aktivität/das Fragment von RecyclerView:

 final CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);

    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(mAdapter);

    recyclerView.setNestedScrollingEnabled(false); // Disables scrolling for RecyclerView, CustomLinearLayoutManager used instead of MyLinearLayoutManager
    recyclerView.setHasFixedSize(false);

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            int visibleItemCount = layoutManager.getChildCount();
            int totalItemCount = layoutManager.getItemCount();
            int lastVisibleItemPos = layoutManager.findLastVisibleItemPosition();
            Log.i("getChildCount", String.valueOf(visibleItemCount));
            Log.i("getItemCount", String.valueOf(totalItemCount));
            Log.i("lastVisibleItemPos", String.valueOf(lastVisibleItemPos));
            if ((visibleItemCount + lastVisibleItemPos) >= totalItemCount) {
                Log.i("LOG", "Last Item Reached!");
            }
        }
    });
0
Soni Kumar