Mam kartę DialogFragment
zawierającą RecyclerView
(listę kart).
W tym RecyclerView
jest jeden lub więcej, CardViews
które mogą mieć dowolną wysokość.
Chcę nadać temu DialogFragment
prawidłową wysokość na podstawie tych, CardViews
które są w niej zawarte.
Zwykle byłoby to proste, ustawiłbym wrap_content
się w RecyclerView
ten sposób.
<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>
Ponieważ używam RecyclerView
to nie działa zobacz:
https://issuetracker.google.com/issues/37001674
i
Wysokość widoku zagnieżdżonego recyklingu nie zawija treści
Na obu tych stronach ludzie sugerują rozszerzenie LinearLayoutManager
i zastąpienieonMeasure()
Najpierw użyłem LayoutManager, który ktoś podał w pierwszym łączu:
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);
}
}
}
Jednak to nie zadziałało, ponieważ
heightSize = View.MeasureSpec.getSize(heightSpec);
zwraca bardzo dużą wartość, która wydaje się być powiązana match_parent
.
Komentując height = heightSize;
(w drugim przypadku przełącznika) udało mi się sprawić, by wysokość działała, ale tylko wtedy, gdy TextView
dziecko wewnątrz CardView
nie zawija własnego tekstu (długie zdanie).
Gdy tylko zostanie TextView
zawinięty własny tekst, wysokość MUSI wzrosnąć, ale nie wzrośnie. Obliczono wysokość tego długiego zdania jako pojedynczą linię, a nie linię zawiniętą (2 lub więcej).
Wszelkie porady na temat tego, jak powinienem to poprawić, LayoutManager
aby moje RecyclerView
prace WRAP_CONTENT
?
Edycja: ten menedżer układu może działać dla większości osób, ale nadal ma problemy z przewijaniem i obliczaniem wysokości zawijania widoków tekstu
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);
}
}
}
źródło
Jan 22, 2016: This has been merged into the internal tree, should be available with the next version of support library.
Odpowiedzi:
Z aktualizacji aktualizacji 23.2.1 Biblioteki obsługi systemu Android wszystkie WRAP_CONTENT powinny działać poprawnie.
Zaktualizuj wersję biblioteki w
gradle
pliku LUB, aby dodatkowo:rozwiązano niektóre problemy, takie jak Naprawiono błędy związane z różnymi metodami specyfikacji
Sprawdź http://developer.android.com/tools/support-library/features.html#v7-recyclerview
możesz sprawdzić historię wersji Biblioteki pomocy technicznej
źródło
23.2.0
go, aby zawiesić aplikację. Więc podążyłem za twoją odpowiedzią i mojeRecyclerView
opakowanie się nie zawija. Czemu?mRecyclerView.setNestedScrollingEnabled(false);
przeciwnym razie widok recyklera nadal obsłuży sam przewijanie, aby przekazać zdarzenia rodzicom.AKTUALIZACJA 02.07.2020
Ta metoda może zapobiegać recyklingowi i nie powinna być stosowana w przypadku dużych zbiorów danych .
AKTUALIZACJA 05.07.2019
Jeśli używasz
RecyclerView
wewnątrzScrollView
, po prostu zmieńScrollView
naandroidx.core.widget.NestedScrollView
. Wewnątrz tego widoku nie ma potrzeby spakowaniaRecyclerView
wewnątrzRelativeLayout
.W końcu znalazłem rozwiązanie tego problemu.
Wszystko, co musisz zrobić, to owinąć
RecyclerView
w sposóbRelativeLayout
. Może są też inne widoki, które również mogą działać.źródło
Oto wyrafinowana wersja klasy, która wydaje się działać i nie ma problemów, które mają inne rozwiązania:
Jest to również dostępne jako biblioteka . Link do odpowiedniej klasy .
źródło
onBindViewHolder()
zostanie nazwane. To źle, ponieważ w tym momencie dzwonię, na przykład,holder.textView.setText(longText)
aby dziecko stało się wyższe, ale nie ma to odzwierciedlenia w wysokości recyklera. Jeśli masz jakiś pomysł (na przykład szybkie zmiany w adapterze), byłbym wdzięczny.RecyclerView
wewnątrz pionowejRecyclerView
.AKTUALIZACJA
Dzięki aktualizacji Biblioteki pomocy Android 23.2 wszystkie WRAP_CONTENT powinny działać poprawnie.
Zaktualizuj wersję biblioteki w pliku stopniowym.
Oryginalna odpowiedź
Zgodnie z odpowiedzią na inne pytanie, musisz użyć oryginalnej metody onMeasure (), gdy wysokość widoku recyklera jest większa niż wysokość ekranu. Ten menedżer układu może obliczyć elementDekoracja i przewijać z większą liczbą.
oryginalna odpowiedź: https://stackoverflow.com/a/28510031/1577792
źródło
gridlayoutmanager
istaggeredgridlayoutmanager
biorąc pod uwagę liczbę rozpiętości w umyśleOto wersja c # dla Androida mono
źródło
var p = (RecyclerView.LayoutParams) child.LayoutParameters
zvar p = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>()
RecyclerView
dodano wsparcie dla,wrap_content
w23.2.0
którym był błąd, 23.2.1 było po prostu stabilne, więc możesz użyć:Możesz zobaczyć historię zmian tutaj:
https://developer.android.com/topic/libraries/support-library/revisions.html
Uwaga:
Należy również pamiętać, że po aktualizacji biblioteki wsparcia
RecyclerView
będzie szanować,wrap_content
a takżematch_parent
, jeśli masz widok elementuRecyclerView
zestawu, ponieważmatch_parent
pojedynczy widok wypełni cały ekranźródło
Ten komentarz pomógł mi.
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.
źródło
Problem z przewijaniem i zawijaniem tekstu polega na tym, że ten kod zakłada, że zarówno szerokość, jak i wysokość są ustawione na
wrap_content
. Należy jednakLayoutManager
wiedzieć, że szerokość pozioma jest ograniczona. Zamiast tworzyć własnewidthSpec
dla każdego widoku potomnego, wystarczy użyć oryginałuwidthSpec
:źródło
Spróbuj tego (To paskudne rozwiązanie, ale może działać): W
onCreate
metodzie twojegoActivity
lub wonViewCreated
metodzie twojego fragmentu. Ustaw oddzwanianie gotowe do uruchomienia przyRecyclerView
pierwszym renderowaniu, na przykład:W
calculeRecyclerViewFullHeight
obliczeniuRecyclerView
pełnej wysokości opartej na wysokości jego dzieci.W moim przypadku mój
RecyclerView
jestSwipeRefreshLayout
z tego powodu ustawiam wysokość na,SwipeRefreshView
a nie na,RecyclerView
ale jeśli nie maszSwipeRefreshView
, możeszRecyclerView
zamiast tego ustawić wysokość .Daj mi znać, czy to ci pomogło, czy nie.
źródło
RecyclerView
instancję.Działa to teraz, ponieważ wydali wersję 23.2, jak stwierdzono w tym poście . Cytując oficjalny blog
źródło
Wystarczy umieścić RecyclerView w NestedScrollView. Działa świetnie
źródło
Użyłem niektórych z powyższych rozwiązań, ale to działało,
width
aleheight
.compileSdkVersion
większa niż 23 , można korzystać bezpośrednio RecyclerView przewidziane w swoich bibliotekach podtrzymujących recyklera widzenia, jak na 23 to będzie'com.android.support:recyclerview-v7:23.2.1'
. Te biblioteki pomocnicze obsługują atrybutywrap_content
dla szerokości i wysokości.Musisz dodać to do swoich zależności
compileSdkVersion
mniej niż 23 lata , możesz skorzystać z niżej wymienionego rozwiązania.Znalazłem ten wątek Google dotyczący tego problemu. W tym wątku jest jeden wkład, który prowadzi do implementacji LinearLayoutManager .
Przetestowałem go zarówno pod względem wysokości, jak i szerokości . W obu przypadkach działał dobrze.
źródło
Zamiast korzystać z dowolnej biblioteki, najłatwiejszym rozwiązaniem do czasu pojawienia się nowej wersji jest po prostu otwarcie b.android.com/74772 . Z łatwością znajdziesz tam najlepsze znane do tej pory rozwiązanie.
PS: b.android.com/74772#c50 pracował dla mnie
źródło
sugeruję, aby umieścić widok recyklera w dowolnym innym układzie (preferowany jest układ względny). Następnie zmień wysokość / szerokość recyclinglerview jako dopasuj element nadrzędny do tego układu i ustaw wysokość / szerokość układu nadrzędnego jako zawartość zawijania. mi to pasuje
źródło
Zamień,
measureScrapChild
aby śledzić kod:Używam xamarin, więc jest to kod c #. Myślę, że można to łatwo „przetłumaczyć” na Javę.
źródło
Zaktualizuj widok za pomocą wartości null zamiast nadrzędnej grupy widoków w module wyświetlającym adaptera w metodzie onCreateViewHolder.
źródło
Musisz umieścić FrameLayout jako Widok główny, a następnie umieścić w RelativeLayout za pomocą ScrollView i przynajmniej RecyclerView, to działa dla mnie.
Prawdziwa sztuczka to RelativeLayout ...
Chętnie pomoże.
źródło
Nie pracowałem nad moją odpowiedzią, ale tak, jak ją znam StaggridLayoutManager bez. siatki 1 może rozwiązać Twój problem, ponieważ StaggridLayout automatycznie dostosuje swoją wysokość i szerokość do rozmiaru zawartości. jeśli to działa, nie zapomnij sprawdzić poprawnej odpowiedzi.
źródło