Ich habe eine DialogFragment
, die eine enthält RecyclerView
(eine Liste von Karten).
Darin RecyclerView
befinden sich eine oder mehrere CardViews
, die eine beliebige Höhe haben können.
Ich möchte diesem DialogFragment
die richtige Höhe geben, basierend auf den CardViews
darin enthaltenen.
Normalerweise wäre dies einfach, ich setzen würde wrap_content
auf das RecyclerView
so.
<android.support.v7.widget.RecyclerView ...
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:scrollbars="vertical" >
</android.support.v7.widget.RecyclerView>
Da ich ein benutze RecyclerView
das nicht funktioniert siehe:
https://issuetracker.google.com/issues/37001674
und
Die Höhe der verschachtelten Recycler-Ansicht umschließt den Inhalt nicht
Auf beiden Seiten wird empfohlen, diese zu erweitern LinearLayoutManager
und zu überschreibenonMeasure()
Ich habe zuerst den LayoutManager verwendet , den jemand im ersten Link angegeben hat:
public static class WrappingLayoutManager extends LinearLayoutManager {
public WrappingLayoutManager(Context context) {
super(context);
}
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);
measureScrapChild(recycler, 0,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
int width = mMeasuredDimension[0];
int height = mMeasuredDimension[1];
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
width = widthSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
height = heightSize;
break;
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 != 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();
measuredDimension[1] = view.getMeasuredHeight();
recycler.recycleView(view);
}
}
}
Dies funktionierte jedoch nicht, weil
heightSize = View.MeasureSpec.getSize(heightSpec);
Gibt einen sehr großen Wert zurück, der in Beziehung zu stehen scheint match_parent
.
Durch Kommentieren height = heightSize;
(im zweiten Schalterfall) gelang es mir, die Höhe zum Laufen zu bringen, aber nur, wenn ein TextView
Kind im Inneren CardView
keinen eigenen Text umschließt (ein langer Satz).
Sobald TextView
dies seinen eigenen Text umschließt, sollte die Höhe erhöht werden, aber dies ist nicht der Fall. Die Höhe für diesen langen Satz wurde als einzelne Zeile berechnet, nicht als umbrochene Zeile (2 oder mehr).
Irgendwelche Ratschläge, wie ich das verbessern soll, LayoutManager
damit ich damit RecyclerView
arbeite WRAP_CONTENT
?
Bearbeiten: Dieser Layout-Manager funktioniert möglicherweise für die meisten Benutzer, hat jedoch weiterhin Probleme beim Scrollen und Berechnen der Höhe beim Umschließen von Textansichten
public class MyLinearLayoutManager extends LinearLayoutManager {
public MyLinearLayoutManager(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++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
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 != 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);
}
}
}
quelle
Jan 22, 2016: This has been merged into the internal tree, should be available with the next version of support library.
Antworten:
Ab dem Update der Android Support Library 23.2.1 sollten alle WRAP_CONTENT ordnungsgemäß funktionieren.
Bitte aktualisieren Sie die Version einer Bibliothek in der
gradle
Datei ODER auf weitere:Einige Probleme wurden behoben, z. B. Fehler im Zusammenhang mit verschiedenen Methoden für Messspezifikationen behoben
Überprüfen Sie http://developer.android.com/tools/support-library/features.html#v7-recyclerview
Sie können den Versionsverlauf der Support Library überprüfen
quelle
23.2.0
stürzt meine App ab. Also bin ich deiner Antwort gefolgt und meineRecyclerView
ist nicht verpackt. Warum?mRecyclerView.setNestedScrollingEnabled(false);
sonst die Recycler-Ansicht das Scrollen selbst übernimmt, um die Ereignisse an die Eltern weiterzuleiten.UPDATE 05.07.2019
Wenn Sie
RecyclerView
in a verwendenScrollView
, wechseln Sie einfachScrollView
zuandroidx.core.widget.NestedScrollView
. Innerhalb dieser Ansicht gibt es keine Notwendigkeit zu packenRecyclerView
innen einRelativeLayout
.Endlich die Lösung für dieses Problem gefunden.
Alles was Sie tun müssen, ist das
RecyclerView
in ein zu wickelnRelativeLayout
. Vielleicht gibt es andere Ansichten, die auch funktionieren können.quelle
Hier ist die verfeinerte Version der Klasse, die zu funktionieren scheint und keine Probleme hat, die andere Lösungen haben:
Dies ist auch als Bibliothek verfügbar . Link zur relevanten Klasse .
quelle
onBindViewHolder()
es aufgerufen wird. Das ist schlecht, weil ich an diesem Punkt zum Beispielholder.textView.setText(longText)
anrufe, damit das Kind größer wird, aber es spiegelt sich nicht in der Höhe des Recyclers wider. Wenn Sie eine Idee haben (wie schnelle Änderungen am Adapter), wäre ich Ihnen dankbar.RecyclerView
innerhalb der Vertikalen zuRecyclerView
überwinden .AKTUALISIEREN
Mit dem Update der Android Support Library 23.2 sollten alle WRAP_CONTENT ordnungsgemäß funktionieren.
Bitte aktualisieren Sie die Version einer Bibliothek in der Gradle-Datei.
Ursprüngliche Antwort
Wie bei einer anderen Frage beantwortet, müssen Sie die ursprüngliche onMeasure () -Methode verwenden, wenn die Höhe Ihrer Recycler-Ansicht größer als die Bildschirmhöhe ist. Dieser Layout-Manager kann ItemDecoration berechnen und mit mehr scrollen.
ursprüngliche Antwort: https://stackoverflow.com/a/28510031/1577792
quelle
gridlayoutmanager
undstaggeredgridlayoutmanager
die Anzahl der Spannen berücksichtigenHier ist die c # -Version für Mono Android
quelle
var p = (RecyclerView.LayoutParams) child.LayoutParameters
durchvar p = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>()
RecyclerView
Unterstützung fürwrap_content
in23.2.0
denen war fehlerhaft, 23.2.1 war nur stabil, so dass Sie verwenden können:Sie können den Revisionsverlauf hier sehen:
https://developer.android.com/topic/libraries/support-library/revisions.html
Hinweis:
Beachten Sie auch , dass Support - Bibliothek nach der Aktualisierung der
RecyclerView
respektierenwrap_content
sowiematch_parent
so , wenn Sie einen Artikel Ansicht eines habenRecyclerView
Satz wiematch_parent
der Einzelansicht wird gesamten Bildschirm füllenquelle
Dieser Kommentar hat mir geholfen.
Put the recyclerview in any other layout (Relative layout is preferable). Then change recyclerview's height/width as match parent to that layout and set the parent layout's height/width as wrap content.
quelle
Das Problem beim Scrollen und Umbrechen von Text besteht darin, dass dieser Code davon ausgeht, dass sowohl die Breite als auch die Höhe auf eingestellt sind
wrap_content
. EsLayoutManager
muss jedoch bekannt sein, dass die horizontale Breite eingeschränkt ist.widthSpec
Verwenden Sie also nicht das Original für jede untergeordnete Ansicht, sondern verwenden Sie einfach das OriginalwidthSpec
:quelle
Versuchen Sie dies (es ist eine böse Lösung, aber es kann funktionieren): In der
onCreate
Methode IhresActivity
oder in deronViewCreated
Methode Ihres Fragments. Stellen Sie einen Rückruf so ein, dass er beimRecyclerView
ersten Rendern ausgelöst wird :In der
calculeRecyclerViewFullHeight
Berechnung derRecyclerView
vollen Größe basierend auf der Größe seiner Kinder.In meinem Fall ist my
RecyclerView
in a enthalten. AusSwipeRefreshLayout
diesem Grund setze ich die Höhe aufSwipeRefreshView
und nicht auf,RecyclerView
aber wenn Sie keine haben, könnenSwipeRefreshView
SieRecyclerView
stattdessen die Höhe auf einstellen .Lassen Sie mich wissen, ob dies Ihnen geholfen hat oder nicht.
quelle
RecyclerView
Instanz zurückgibt .Dies funktioniert jetzt, da sie eine Version in Version 23.2 veröffentlicht haben, wie in diesem Beitrag angegeben . Zitiert den offiziellen Blogpost
quelle
Fügen Sie einfach Ihre RecyclerView in eine NestedScrollView ein. Funktioniert perfekt
quelle
Ich hatte einige der oben genannten Lösungen verwendet, aber es funktionierte
width
aberheight
.compileSdkVersion
größer als 23 ist , können Sie RecyclerView direkt verwenden, das in den jeweiligen Unterstützungsbibliotheken der Recycler-Ansicht bereitgestellt wird, wie dies bei 23 der Fall ist'com.android.support:recyclerview-v7:23.2.1'
. Diese Unterstützungsbibliotheken unterstützen Attributewrap_content
für Breite und Höhe.Sie müssen es zu Ihren Abhängigkeiten hinzufügen
compileSdkVersion
weniger als 23 Jahre alt sind, können Sie die unten genannte Lösung verwenden.Ich habe diesen Google-Thread zu diesem Problem gefunden. In diesem Thread gibt es einen Beitrag, der zur Implementierung von LinearLayoutManager führt .
Ich habe es sowohl auf Höhe als auch auf Breite getestet und es hat in beiden Fällen gut funktioniert.
quelle
Anstatt eine Bibliothek zu verwenden, ist es am einfachsten, b.android.com/74772 zu öffnen, bis die neue Version herauskommt . Dort finden Sie leicht die beste bisher bekannte Lösung.
PS: b.android.com/74772#c50 hat bei mir funktioniert
quelle
Ich empfehle Ihnen, die Recycling-Ansicht in ein anderes Layout einzufügen (ein relatives Layout ist vorzuziehen). Ändern Sie dann die Höhe / Breite von recyclerview als übergeordnetes Element zu diesem Layout und legen Sie die Höhe / Breite des übergeordneten Layouts als Wrap-Inhalt fest. Für mich geht das
quelle
Ersetzen Sie,
measureScrapChild
um dem folgenden Code zu folgen:Ich benutze Xamarin, das ist also C # -Code. Ich denke, dies kann leicht nach Java "übersetzt" werden.
quelle
Aktualisieren Sie Ihre Ansicht mit dem Wert null anstelle der übergeordneten Ansichtsgruppe in der onCreateViewHolder-Methode des Adapter-Ansichtsinhabers.
quelle
Sie müssen ein FrameLayout als Hauptansicht einfügen und dann mit ScrollView und zumindest Ihrem RecyclerView in ein RelativeLayout einfügen. Es funktioniert für mich.
Der wahre Trick hier ist das RelativeLayout ...
Freue mich zu helfen.
quelle
Ich habe nicht an meiner Antwort gearbeitet, aber so wie ich sie kenne StaggridLayoutManager mit nein. von Raster 1 kann Ihr Problem lösen, da StaggridLayout seine Höhe und Breite automatisch an die Größe des Inhalts anpasst. Wenn es funktioniert, vergessen Sie nicht, es als richtige Antwort zu überprüfen.
quelle