J'ai un DialogFragment
qui contient un RecyclerView
(une liste de cartes).
À l'intérieur, il RecyclerView
y en a un ou plusieurs CardViews
qui peuvent avoir n'importe quelle hauteur.
Je veux lui donner DialogFragment
la hauteur correcte en fonction de ce CardViews
qui est contenu à l'intérieur.
Normalement, ce serait simple, je me mettrais wrap_content
sur la RecyclerView
même chose.
<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>
Parce que j'utilise un RecyclerView
cela ne fonctionne pas voir:
https://issuetracker.google.com/issues/37001674
et
La hauteur de la vue du recycleur imbriqué n'enveloppe pas son contenu
Sur ces deux pages, les utilisateurs suggèrent d'étendre LinearLayoutManager
et de remplaceronMeasure()
J'ai d'abord utilisé le LayoutManager que quelqu'un a fourni dans le premier lien:
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);
}
}
}
Cependant, cela n'a pas fonctionné car
heightSize = View.MeasureSpec.getSize(heightSpec);
renvoie une très grande valeur qui semble être liée à match_parent
.
En commentant height = heightSize;
(dans le deuxième cas de commutateur) j'ai réussi à faire fonctionner la hauteur mais seulement si un TextView
enfant à l'intérieur du CardView
n'emballe pas son propre texte (une longue phrase).
Dès que cela TextView
enveloppe son propre texte, la hauteur DEVRAIT augmenter mais ce n'est pas le cas. Il a calculé la hauteur de cette longue phrase comme une seule ligne, pas une ligne encapsulée (2 ou plus).
Des conseils sur la façon dont je devrais améliorer cela LayoutManager
pour que je RecyclerView
travaille avec WRAP_CONTENT
?
Modifier: ce gestionnaire de mise en page peut fonctionner pour la plupart des gens, mais il a toujours des problèmes avec le défilement et le calcul de la hauteur des vues de texte d'habillage
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);
}
}
}
la source
Jan 22, 2016: This has been merged into the internal tree, should be available with the next version of support library.
Réponses:
À partir de la mise à jour 23.2.1 de la bibliothèque de support Android , tous les WRAP_CONTENT devraient fonctionner correctement.
Veuillez mettre à jour la version d'une bibliothèque dans le
gradle
fichier OU pour continuer:a résolu un problème tel que Correction de bugs liés à diverses méthodes de spécifications de mesure
Consultez http://developer.android.com/tools/support-library/features.html#v7-recyclerview
vous pouvez vérifier l' historique des révisions de la bibliothèque de support
la source
23.2.0
commence à planter mon application. Donc, j'ai suivi votre réponse et monRecyclerView
n'est pas enveloppant. Pourquoi?mRecyclerView.setNestedScrollingEnabled(false);
sinon la vue du recycleur gérera toujours le défilement elle-même à la place pour transmettre les événements aux parents.UPDATE 02.07.2020
Cette méthode peut empêcher le recyclage et ne doit pas être utilisée sur de grands ensembles de données .
MISE À JOUR 05.07.2019
Si vous utilisez à l'
RecyclerView
intérieur d'unScrollView
, changez simplementScrollView
enandroidx.core.widget.NestedScrollView
. À l'intérieur de cette vue, il n'est pas nécessaire d'emballerRecyclerView
dans un fichierRelativeLayout
.Enfin trouvé la solution à ce problème.
Tout ce que vous avez à faire est d'envelopper le fichier
RecyclerView
dans un fichierRelativeLayout
. Il y a peut-être d'autres vues qui peuvent également fonctionner.la source
Voici la version raffinée de la classe qui semble fonctionner et qui manque de problèmes aux autres solutions:
Ceci est également disponible sous forme de bibliothèque . Lien vers la classe pertinente .
la source
onBindViewHolder()
être appelé. C'est mauvais parce qu'à ce stade, j'appelle, par exemple,holder.textView.setText(longText)
pour que l'enfant devienne plus grand, mais cela ne se reflète pas dans la hauteur du recycleur. Si vous avez une idée (comme des modifications rapides de l'adaptateur), je vous en serais reconnaissant.RecyclerView
intérieur verticalRecyclerView
.METTRE À JOUR
Avec la mise à jour 23.2 de la bibliothèque de support Android, tous les WRAP_CONTENT devraient fonctionner correctement.
Veuillez mettre à jour la version d'une bibliothèque dans le fichier gradle.
Réponse originale
Comme répondu à une autre question, vous devez utiliser la méthode onMeasure () originale lorsque la hauteur de vue de votre recycleur est supérieure à la hauteur de l'écran. Ce gestionnaire de mise en page peut calculer ItemDecoration et peut faire défiler avec plus.
réponse originale: https://stackoverflow.com/a/28510031/1577792
la source
gridlayoutmanager
et enstaggeredgridlayoutmanager
tenant compte du nombre de span à l'espritVoici la version c # pour mono android
la source
var p = (RecyclerView.LayoutParams) child.LayoutParameters
parvar p = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>()
RecyclerView
Ajout du support pourwrap_content
dans23.2.0
lequel était bogué, 23.2.1 était juste stable, vous pouvez donc utiliser:Vous pouvez voir l'historique des révisions ici:
https://developer.android.com/topic/libraries/support-library/revisions.html
Remarque:
Notez également qu'après la mise à jour de la bibliothèque de support, le
RecyclerView
respecterawrap_content
égalementmatch_parent
si vous avez une vue d'élément d'unRecyclerView
ensemble carmatch_parent
la vue unique remplira tout l'écran.la source
Ce commentaire m'a aidé.
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.
la source
Le problème avec le défilement et l'habillage de texte est que ce code suppose que la largeur et la hauteur sont définies sur
wrap_content
. Cependant, ilLayoutManager
faut savoir que la largeur horizontale est contrainte. Donc, au lieu de créer la vôtrewidthSpec
pour chaque vue enfant, utilisez simplement l'originalwidthSpec
:la source
Essayez ceci (c'est une mauvaise solution mais cela peut fonctionner): Dans la
onCreate
méthode de votreActivity
ou dans laonViewCreated
méthode de votre fragment. Définissez un rappel prêt à être déclenché lors duRecyclerView
premier rendu, comme ceci:Dans le
calculeRecyclerViewFullHeight
calculez laRecyclerView
hauteur totale en fonction de la hauteur de ses enfants.Dans mon cas, my
RecyclerView
is contain in aSwipeRefreshLayout
pour cette raison, je règle la hauteur sur leSwipeRefreshView
et non sur le,RecyclerView
mais si vous n'en avez pas,SwipeRefreshView
vous pouvez définir la hauteur sur le à laRecyclerView
place.Faites-moi savoir si cela vous a aidé ou non.
la source
RecyclerView
instance.Cela fonctionne maintenant car ils ont fait une version dans la version 23.2, comme indiqué dans cet article . Citant le blog officiel
la source
Placez simplement votre RecyclerView dans un NestedScrollView. Fonctionne parfaitement
la source
J'avais utilisé certaines des solutions ci-dessus, mais cela fonctionnait pour
width
maisheight
.compileSdkVersion
supérieure à 23 , vous pouvez directement utiliser RecyclerView fourni dans leurs bibliothèques de support respectives de la vue recycleur, comme pour 23 ce sera'com.android.support:recyclerview-v7:23.2.1'
. Ces bibliothèques prennent en charge les attributs dewrap_content
largeur et de hauteur.Vous devez l'ajouter à vos dépendances
compileSdkVersion
moins de 23 ans , vous pouvez utiliser la solution mentionnée ci-dessous.J'ai trouvé ce fil de discussion Google concernant ce problème. Dans ce fil, il y a une contribution qui mène à l'implémentation de LinearLayoutManager .
Je l'ai testé à la fois pour la hauteur et la largeur et cela a bien fonctionné pour moi dans les deux cas.
la source
Au lieu d'utiliser une bibliothèque, la solution la plus simple jusqu'à la sortie de la nouvelle version consiste simplement à ouvrir b.android.com/74772 . Vous y trouverez facilement la meilleure solution connue à ce jour.
PS: b.android.com/74772#c50 a fonctionné pour moi
la source
Je vous suggère de mettre le recyclerview dans n'importe quelle autre mise en page (la mise en page relative est préférable). Modifiez ensuite la hauteur / largeur de recyclerview en tant que parent correspondant à cette mise en page et définissez la hauteur / largeur de la mise en page parente comme contenu d'habillage. ça marche pour moi
la source
Remplacer
measureScrapChild
pour suivre le code:J'utilise xamarin, c'est donc du code c #. Je pense que cela peut être facilement "traduit" en Java.
la source
Mettez à jour votre vue avec une valeur nulle au lieu du groupe de vues parent dans la méthode onCreateViewHolder de la visionneuse de l'adaptateur.
la source
Vous devez mettre un FrameLayout comme vue principale puis mettre dans un RelativeLayout avec ScrollView et au moins votre RecyclerView, cela fonctionne pour moi.
Le vrai truc ici est le RelativeLayout ...
Heureux d'aider.
la source
Je n'ai pas travaillé sur ma réponse mais la façon dont je la connais StaggridLayoutManager sans. de la grille 1 peut résoudre votre problème car StaggridLayout ajustera automatiquement sa hauteur et sa largeur en fonction de la taille du contenu. si cela fonctionne, n'oubliez pas de le vérifier comme une bonne réponse.
la source