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:
ScrollView
(jetzt ScrollView
enthält RecyclerView
) - kann die Karte bis zur RecyclerView
sehenviewGroup
mithilfe von RecyclerView
anstelle von ScrollView
zu implementieren, wobei einer der Sichttypen CardView
ist, aber ich habe genau dieselben Ergebnisse wie mit ScrollView
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
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:
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;
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) {
}
});
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äß.
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.
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.
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");
}
}
}
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);
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
Wenn Sie RecyclerView
in NestedScrollView
eingeben und recyclerView.setNestedScrollingEnabled(false);
aktivieren, wird beim Scrollen gut funktionieren.
Allerdings gibt es ein Problem
RecyclerView
recycle 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
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.
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);
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
Das macht den Trick:
recyclerView.setNestedScrollingEnabled(false);
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.
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.
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>
Wenn RecyclerView nur eine Zeile in ScrollView anzeigt. Sie müssen nur die Höhe Ihrer Zeile auf Android:layout_height="wrap_content"
setzen.
sie können den LinearLayoutManager auch überschreiben, damit die Recyclingübersicht reibungslos läuft
@Override
public boolean canScrollVertically(){
return false;
}
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!");
}
}
});