ATUALIZAÇÃO 1
Desde a Biblioteca de suporte Android 23.2.0, foi adicionado um método setAutoMeasureEnabled(true)para o LayoutManagers. Faz o RecyclerView envolver seu conteúdo e funciona como um encanto.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
Então, basta adicionar algo como isto:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
ATUALIZAÇÃO 2
Como o 27.1.0 setAutoMeasureEnabledestá obsoleto, você deve fornecer a implementação personalizada do LayoutManager com o método substituídoisAutoMeasureEnabled()
Porém, após muitos casos de uso do RecyclerView, recomendo vivamente não usá-lo no modo de agrupamento , pois não é para isso que ele se destina. Tente refatorar todo o seu layout usando o RecyclerView único normal com vários tipos de itens. Ou use a abordagem com LinearLayout que descrevi abaixo como último recurso
Resposta antiga (não recomendada)
Você pode usar RecyclerViewdentro NestedScrollView. Antes de tudo, você deve implementar seu próprio costume LinearLayoutManager, pois ele RecyclerViewenvolve seu conteúdo. Por exemplo:
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);
}
}
Depois disso, use isso LayoutManagerpara o seuRecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
Mas você também deve chamar esses dois métodos:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
setNestedScrollingEnabled(false)Desative aqui a rolagem para RecyclerViewque não intercepte o evento de rolagem NestedScrollView. E setHasFixedSize(false)determine que as alterações no conteúdo do adaptador podem alterar o tamanho doRecyclerView
Nota importante: Em alguns casos, esta solução é pouco problemática e tem problemas de desempenho; portanto, se você tiver muitos itens, RecyclerViewrecomendo usar a LinearLayoutimplementação personalizada da exibição de lista, crie um análogo do Adapter e faça com que comportar-se como ListViewouRecyclerView