ACTUALIZACIÓN 1
Desde Android Support Library 23.2.0 se agregaron métodos setAutoMeasureEnabled(true)
para LayoutManagers. Hace que RecyclerView ajuste su contenido y funciona de maravilla.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
Así que solo agrega algo como esto:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
ACTUALIZACIÓN 2
Dado que 27.1.0 setAutoMeasureEnabled
está en desuso, debe proporcionar una implementación personalizada de LayoutManager con un método anuladoisAutoMeasureEnabled()
Pero después de muchos casos de uso de RecyclerView, recomiendo no usarlo en modo envolvente , porque esto no es para lo que está destinado. Intente refactorizar todo su diseño usando RecyclerView normal con varios tipos de elementos. O utilice el enfoque con LinearLayout que describí a continuación como último recurso
Respuesta anterior (no recomendada)
Puedes usar RecyclerView
dentro NestedScrollView
. En primer lugar, debe implementar su propia costumbre LinearLayoutManager
, hace RecyclerView
que su contenido se ajuste. Por ejemplo:
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);
}
}
Después de eso, use esto LayoutManager
para suRecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
Pero también debe llamar a esos dos métodos:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
Aquí setNestedScrollingEnabled(false)
deshabilita el desplazamiento para RecyclerView
, por lo que no intercepta el evento de desplazamiento NestedScrollView
. Y setHasFixedSize(false)
determine que los cambios en el contenido del adaptador pueden cambiar el tamaño delRecyclerView
Nota importante: esta solución es un poco defectuosa en algunos casos y tiene problemas con el rendimiento, por lo que si tiene muchos elementos en su RecyclerView
recomendaría utilizar una LinearLayout
implementación personalizada de la vista de lista, cree un adaptador análogo y hágalo comportarse como ListView
oRecyclerView