MISE À JOUR 1
Depuis la bibliothèque de support Android 23.2.0, une méthode a été ajoutée setAutoMeasureEnabled(true)
pour les LayoutManagers. Il fait recyclerView pour envelopper son contenu et fonctionne comme un charme.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
Alors ajoutez simplement quelque chose comme ceci:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
MISE À JOUR 2
Étant donné que 27.1.0 setAutoMeasureEnabled
est obsolète, vous devez donc fournir une implémentation personnalisée de LayoutManager avec la méthode substituéeisAutoMeasureEnabled()
Mais après de nombreux cas d'utilisation de RecyclerView, je recommande fortement de ne pas l'utiliser dans mode d'emballage , car ce n'est pas ce à quoi il est destiné. Essayez de refaçonner l'ensemble de votre mise en page en utilisant un seul RecyclerView normal avec plusieurs types d'éléments. Ou utilisez l'approche avec LinearLayout que j'ai décrite ci-dessous en dernier recours
Ancienne réponse (non recommandée)
Vous pouvez utiliser à l' RecyclerView
intérieur NestedScrollView
. Tout d'abord, vous devez implémenter votre propre personnalisation LinearLayoutManager
, cela vous permet RecyclerView
d'envelopper son contenu. Par exemple:
public class WrappingLinearLayoutManager extends LinearLayoutManager
{
public WrappingLinearLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
@Override
public boolean canScrollVertically() {
return false;
}
@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(0, View.MeasureSpec.UNSPECIFIED),
heightSpec,
mMeasuredDimension);
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
measureScrapChild(recycler, i,
widthSpec,
View.MeasureSpec.makeMeasureSpec(0, 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);
if (view.getVisibility() == View.GONE) {
measuredDimension[0] = 0;
measuredDimension[1] = 0;
return;
}
// For adding Item Decor Insets to view
super.measureChildWithMargins(view, 0, 0);
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
p.height);
view.measure(childWidthSpec, childHeightSpec);
// Get decorated measurements
measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
Après cela, utilisez ceci LayoutManager
pour votreRecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
Mais vous devez également appeler ces deux méthodes:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
Ici, setNestedScrollingEnabled(false)
désactivez le défilement pour RecyclerView
, afin qu'il n'intercepte pas l'événement de défilement de NestedScrollView
. EtsetHasFixedSize(false)
déterminez que les modifications du contenu de l'adaptateur peuvent modifier la taille duRecyclerView
Remarque importante: cette solution est peu buggée dans certains cas et a des problèmes de performances, donc si vous avez beaucoup d'éléments dans votre, RecyclerView
je vous recommande d'utiliser une LinearLayout
implémentation personnalisée de l'affichage de liste, de créer l'analogue de l'adaptateur pour cela et de le faire se comporter comme ListView
ouRecyclerView