tutorial studio recyclerview imágenes implementar example con como cardview card beautiful and android android-recyclerview android-cardview
vistazo

studio - como implementar cardview en android



Centre una CardView en un RecyclerView con solo un elemento (4)

Estoy usando un RecyclerView que contiene CardViews con un TextView y un ImageView (cada tarjeta representa una ciudad). También tengo un onClickListener en cada tarjeta que me lleva a una lista de museos en la ciudad. (El RecyclerView está poblado por una ArrayList). La lista es un RecyclerView compuesto por el mismo Cardview que se desplaza verticalmente.

Cuando una ciudad tiene un solo museo, ¿cómo puedo mostrar el CardView único en el centro de la pantalla?

Esta es la actividad xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.bebbo203.mymuseum.MuseumActivity"> <android.support.v7.widget.RecyclerView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/recyclerViewMuseum" android:scrollbars="vertical" android:scrollIndicators="none" android:gravity="center_horizontal" /> </RelativeLayout>

Y este es el xml RecyclerView:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:baselineAligned="false" xmlns:card_view="http://schemas.android.com/apk/res-auto"> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="150dp" android:id="@+id/cardView" card_view:cardCornerRadius="2dp" card_view:cardUseCompatPadding="true" android:gravity="center_horizontal" android:animateLayoutChanges="true" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="150dp" android:id="@+id/imageViewList" android:layout_gravity="center_horizontal|top" android:adjustViewBounds="true" android:scaleType="centerCrop"/> <TextView android:id="@+id/textViewList" android:layout_width="match_parent" android:layout_height="150dp" android:textSize="40sp" android:textIsSelectable="false" android:textAlignment="center" android:gravity="fill" android:textStyle="bold" android:layout_weight="1" android:layout_gravity="center_horizontal|top"/> </FrameLayout> </android.support.v7.widget.CardView> </RelativeLayout>`

Gracias por ayudar.

Entonces esta es la actividad principal. Una lista de ciudades. Todo está bien aquí.

Cuando hago clic en Parigi que tiene solo un museo, quería mostrar la tarjeta de visita única en el centro de la pantalla

(Y si es posible, me gustaría hacer que el cardview comience desde el centro de la pantalla, no desde la parte superior. Por ejemplo, si la cardview central está siempre en el centro cuando abro la actividad. Por ejemplo, traducir NationalGallery en el centro manteniendo el orden del otro)


¿Puedes probar esto?

import android.content.Context; import android.graphics.Rect; import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import java.lang.reflect.Field; /** * {@link android.support.v7.widget.LinearLayoutManager} which wraps its content. Note that this class will always * wrap the content regardless of {@link android.support.v7.widget.RecyclerView} layout parameters. * <p/> * Now it''s impossible to run add/remove animations with child views which have arbitrary dimensions (height for * VERTICAL orientation and width for HORIZONTAL). However if child views have fixed dimensions * {@link #setChildSize(int)} method might be used to let the layout manager know how big they are going to be. * If animations are not used at all then a normal measuring procedure will run and child views will be measured during * the measure pass. */ public class WrapContentLinearLayoutManager extends android.support.v7.widget.LinearLayoutManager { private static boolean canMakeInsetsDirty = true; private static Field insetsDirtyField = null; private static final int CHILD_WIDTH = 0; private static final int CHILD_HEIGHT = 1; private static final int DEFAULT_CHILD_SIZE = 100; private final int[] childDimensions = new int[2]; private final RecyclerView view; private int childSize = DEFAULT_CHILD_SIZE; private boolean hasChildSize; private int overScrollMode = ViewCompat.OVER_SCROLL_ALWAYS; private final Rect tmpRect = new Rect(); @SuppressWarnings("UnusedDeclaration") public WrapContentLinearLayoutManager(Context context) { super(context); this.view = null; } @SuppressWarnings("UnusedDeclaration") public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); this.view = null; } @SuppressWarnings("UnusedDeclaration") public WrapContentLinearLayoutManager(RecyclerView view) { super(view.getContext()); this.view = view; this.overScrollMode = ViewCompat.getOverScrollMode(view); } @SuppressWarnings("UnusedDeclaration") public WrapContentLinearLayoutManager(RecyclerView view, int orientation, boolean reverseLayout) { super(view.getContext(), orientation, reverseLayout); this.view = view; this.overScrollMode = ViewCompat.getOverScrollMode(view); } public void setOverScrollMode(int overScrollMode) { if (overScrollMode < ViewCompat.OVER_SCROLL_ALWAYS || overScrollMode > ViewCompat.OVER_SCROLL_NEVER) throw new IllegalArgumentException("Unknown overscroll mode: " + overScrollMode); if (this.view == null) throw new IllegalStateException("view == null"); this.overScrollMode = overScrollMode; ViewCompat.setOverScrollMode(view, overScrollMode); } public static int makeUnspecifiedSpec() { return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); } @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); final boolean hasWidthSize = widthMode != View.MeasureSpec.UNSPECIFIED; final boolean hasHeightSize = heightMode != View.MeasureSpec.UNSPECIFIED; final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY; final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY; final int unspecified = makeUnspecifiedSpec(); if (exactWidth && exactHeight) { // in case of exact calculations for both dimensions let''s use default "onMeasure" implementation super.onMeasure(recycler, state, widthSpec, heightSpec); return; } final boolean vertical = getOrientation() == VERTICAL; initChildDimensions(widthSize, heightSize, vertical); int width = 0; int height = 0; // it''s possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This // happens because their invalidation happens after "onMeasure" method. As a workaround let''s clear the // recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never // called whiles scrolling) recycler.clear(); final int stateItemCount = state.getItemCount(); final int adapterItemCount = getItemCount(); // adapter always contains actual data while state might contain old data (f.e. data before the animation is // done). As we want to measure the view with actual data we must use data from the adapter and not from the // state for (int i = 0; i < adapterItemCount; i++) { if (vertical) { if (!hasChildSize) { if (i < stateItemCount) { // we should not exceed state count, otherwise we''ll get IndexOutOfBoundsException. For such items // we will use previously calculated dimensions measureChild(recycler, i, widthSize, unspecified, childDimensions); } else { logMeasureWarning(i); } } height += childDimensions[CHILD_HEIGHT]; if (i == 0) { width = childDimensions[CHILD_WIDTH]; } if (hasHeightSize && height >= heightSize) { break; } } else { if (!hasChildSize) { if (i < stateItemCount) { // we should not exceed state count, otherwise we''ll get IndexOutOfBoundsException. For such items // we will use previously calculated dimensions measureChild(recycler, i, unspecified, heightSize, childDimensions); } else { logMeasureWarning(i); } } width += childDimensions[CHILD_WIDTH]; if (i == 0) { height = childDimensions[CHILD_HEIGHT]; } if (hasWidthSize && width >= widthSize) { break; } } } if (exactWidth) { width = widthSize; } else { width += getPaddingLeft() + getPaddingRight(); if (hasWidthSize) { width = Math.min(width, widthSize); } } if (exactHeight) { height = heightSize; } else { height += getPaddingTop() + getPaddingBottom(); if (hasHeightSize) { height = Math.min(height, heightSize); } } setMeasuredDimension(width, height); if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) { final boolean fit = (vertical && (!hasHeightSize || height < heightSize)) || (!vertical && (!hasWidthSize || width < widthSize)); ViewCompat.setOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS); } } private void logMeasureWarning(int child) { if (BuildConfig.DEBUG) { Log.w("LinearLayoutManager", "Can''t measure child #" + child + ", previously used dimensions will be reused." + "To remove this message either use #setChildSize() method or don''t run RecyclerView animations"); } } private void initChildDimensions(int width, int height, boolean vertical) { if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) { // already initialized, skipping return; } if (vertical) { childDimensions[CHILD_WIDTH] = width; childDimensions[CHILD_HEIGHT] = childSize; } else { childDimensions[CHILD_WIDTH] = childSize; childDimensions[CHILD_HEIGHT] = height; } } @Override public void setOrientation(int orientation) { // might be called before the constructor of this class is called //noinspection ConstantConditions if (childDimensions != null) { if (getOrientation() != orientation) { childDimensions[CHILD_WIDTH] = 0; childDimensions[CHILD_HEIGHT] = 0; } } super.setOrientation(orientation); } public void clearChildSize() { hasChildSize = false; setChildSize(DEFAULT_CHILD_SIZE); } public void setChildSize(int childSize) { hasChildSize = true; if (this.childSize != childSize) { this.childSize = childSize; requestLayout(); } } private void measureChild(RecyclerView.Recycler recycler, int position, int widthSize, int heightSize, int[] dimensions) { final View child; try { child = recycler.getViewForPosition(position); } catch (IndexOutOfBoundsException e) { if (BuildConfig.DEBUG) { Log.w("LinearLayoutManager", "LinearLayoutManager doesn''t work well with animations. Consider switching them off", e); } return; } final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams(); final int hPadding = getPaddingLeft() + getPaddingRight(); final int vPadding = getPaddingTop() + getPaddingBottom(); final int hMargin = p.leftMargin + p.rightMargin; final int vMargin = p.topMargin + p.bottomMargin; // we must make insets dirty in order calculateItemDecorationsForChild to work makeInsetsDirty(p); // this method should be called before any getXxxDecorationXxx() methods calculateItemDecorationsForChild(child, tmpRect); final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child); final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child); final int childWidthSpec = getChildMeasureSpec(widthSize, hPadding + hMargin + hDecoration, p.width, canScrollHorizontally()); final int childHeightSpec = getChildMeasureSpec(heightSize, vPadding + vMargin + vDecoration, p.height, canScrollVertically()); child.measure(childWidthSpec, childHeightSpec); dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin; dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin; // as view is recycled let''s not keep old measured values makeInsetsDirty(p); recycler.recycleView(child); } private static void makeInsetsDirty(RecyclerView.LayoutParams p) { if (!canMakeInsetsDirty) { return; } try { if (insetsDirtyField == null) { insetsDirtyField = RecyclerView.LayoutParams.class.getDeclaredField("mInsetsDirty"); insetsDirtyField.setAccessible(true); } insetsDirtyField.set(p, true); } catch (NoSuchFieldException e) { onMakeInsertDirtyFailed(); } catch (IllegalAccessException e) { onMakeInsertDirtyFailed(); } } private static void onMakeInsertDirtyFailed() { canMakeInsetsDirty = false; if (BuildConfig.DEBUG) { Log.w("LinearLayoutManager", "Can''t make LayoutParams insets dirty, decorations measurements might be incorrect"); } } }

Ponga este WrapContentLinearLayoutManager en su recyclerview

mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(activity));

Y esto en el xml (con el pariente en el padre)

<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/recyclerViewMuseum" android:scrollbars="vertical" android:scrollIndicators="none"/>

Esto debería funcionar :)


1.Intenta establecer LayoutParams CENTER_IN_PARENT cuando recyclerview tiene 1 hijo
2.O Use un FrameLayout como padre de recyclerView y configure layout_gravity O simplemente calcule el espacio de la vista cardview anterior y establezca marginTop en recyclerView o setTranslationY en recyclerView 4. O agregue un itemDecaration con space''height en Recylerview .

RelativeLayout.LayoutParams rLp = (RelativeLayout.LayoutParams) recyclerView.getLayoutParams(); if(data != null || data.size()>1){ rLp.removeRule(RelativeLayout.CENTER_IN_PARENT); }else{ rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); } recyclerView.setLayoutParams(rLp);

Cuando recyclerView tiene solo un hijo, use este LayoutManager:

import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.ViewGroup; public class FullyLinearLayoutManager extends LinearLayoutManager { private static final String TAG = FullyLinearLayoutManager.class.getSimpleName(); private MeasureEndListener mMeasureEndListener; public FullyLinearLayoutManager(Context context) { super(context); } private float divHeight =0; public FullyLinearLayoutManager(Context context,float height) { super(context); divHeight = height; } public FullyLinearLayoutManager(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); Log.i(TAG, "onMeasure called. /nwidthMode " + widthMode + " /nheightMode " + heightSpec + " /nwidthSize " + widthSize + " /nheightSize " + heightSize + " /ngetItemCount() " + getItemCount()); 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 { // LogUtils.e(mMeasuredDimension[1]); height = height + mMeasuredDimension[1]; if(i!= getItemCount()-1){ height += divHeight; // LogUtils.e(divHeight + "xxx add"+DensityUtils.dp2px(divHeight)); }else{ height += 2*divHeight; // LogUtils.e(divHeight+ "xxx no add"+ DensityUtils.dp2px(divHeight)); } 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: } if(mMeasureEndListener!=null){ mMeasureEndListener.onMeasureEnd(width,height); // new Thread().interrupt(); } setMeasuredDimension(width, height); } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { try { View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException 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); } } catch (Exception e) { e.printStackTrace(); } finally { } } public interface MeasureEndListener{ void onMeasureEnd(int width,int height); } public void setMeasureEndListener(MeasureEndListener mMeasureEndListener){ this.mMeasureEndListener = mMeasureEndListener; } }


Implementé la sencilla aplicación HelloWorld, que muestra la lista de ciudades y según la cantidad de museos que tiene: muestra una tarjeta de ciudad de tamaño completo o la versión centrada y envolvente de la misma.

(Sí, no soy exactamente bueno en artes :-))

Así es como lo hice.

TL; DR:

La parte crucial es ItemDecoration : establezca los artículos correctos compensados ​​y obtendrá lo que necesita; Así es como lo hice:

RecyclerView recyclerViewMuseum = (RecyclerView)findViewById(R.id.recyclerViewMuseum); recyclerViewMuseum.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); recyclerViewMuseum.setAdapter(adapter); recyclerViewMuseum.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (view instanceof CityWithOneMuseumCardView) { int totalWidth = parent.getWidth(); int cardWidth = getResources().getDimensionPixelOffset(R.dimen.small_card_width); int sidePadding = (totalWidth - cardWidth) / 2; sidePadding = Math.max(0, sidePadding); outRect.set(sidePadding, 0, sidePadding, 0); } } });

Aquí está mi modelo: clases de City y Museum :

public class Museum { public String title; public Museum(String title) { this.title = title; } } public class City { public String title; public int imageRes; public List<Museum> museums = new ArrayList<>(); public City(String title, int imageRes) { this.title = title; this.imageRes = imageRes; } }

Luego Vistas: CityWithManyMuseumsCardView y CityWithOneMuseumCardView . Ambos están utilizando helper-interface IItemDisplayer .

public class CityWithOneMuseumCardView extends CardView implements IItemDisplayer<City> { public CityWithOneMuseumCardView(Context context) { super(context); LayoutInflater.from(context).inflate(R.layout.one_museum_layout, this); } @Override public void displayItem(City city) { TextView cityTitleTextView = (TextView)findViewById(R.id.cityTitleTextView); cityTitleTextView.setText(city.title); } } public class CityWithManyMuseumsCardView extends CardView implements IItemDisplayer<City> { public CityWithManyMuseumsCardView(Context context) { super(context); LayoutInflater.from(context).inflate(R.layout.many_museums_layout, this); } @Override public void displayItem(City city) { ImageView cityBackgroundImageView = (ImageView)findViewById(R.id.cityBackgroundImageView); cityBackgroundImageView.setImageResource(city.imageRes); TextView cityTitleTextView = (TextView)findViewById(R.id.cityTitleTextView); cityTitleTextView.setText(city.title); TextView cityNumberOrMuseumsTextView = (TextView)findViewById(R.id.cityNumberOrMuseumsTextView); cityNumberOrMuseumsTextView.setText(String.valueOf(city.museums.size())); } } public interface IItemDisplayer<TItem> { public void displayItem(TItem item); }

Y sus diseños:

<!-- One Museum card --> <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#BB2050AB" android:layout_width="@dimen/small_card_width" android:layout_height="200dp"> <TextView android:background="#AA000000" android:textColor="#FFFFFF" android:text="Only one museum available" android:textSize="16sp" android:padding="4dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/cityTitleTextView" android:layout_gravity="bottom" android:background="#AAFFFFFF" android:textColor="#000000" android:textSize="24sp" android:paddingStart="16dp" android:paddingEnd="16dp" android:gravity="center" android:layout_width="match_parent" android:layout_height="48dp" /> </FrameLayout> <!-- Many museums card --> <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="240dp"> <ImageView android:id="@+id/cityBackgroundImageView" android:scaleType="fitXY" android:layout_width="500dp" android:layout_height="match_parent" /> <TextView android:id="@+id/cityNumberOrMuseumsTextView" android:layout_gravity="top|end" android:background="#AA000000" android:textColor="#FFFFFF" android:textSize="16sp" android:padding="4dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/cityTitleTextView" android:layout_gravity="bottom" android:background="#AA000000" android:textColor="#FFFFFF" android:textSize="24sp" android:paddingStart="16dp" android:paddingEnd="16dp" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="48dp" /> </FrameLayout>

Entonces tenemos que crear un adaptador para nuestro RecyclerView CityAdapter.java

public class CityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { final static int ITEM_TYPE_MANY_MUSEUMS = 0; final static int ITEM_TYPE_ONE_MUSEUM = 1; private List<City> items; public CityAdapter(List<City> items) { this.items = items; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { switch (viewType) { case ITEM_TYPE_MANY_MUSEUMS: return new ViewHolder(new CityWithManyMuseumsCardView(viewGroup.getContext())); case ITEM_TYPE_ONE_MUSEUM: return new ViewHolder(new CityWithOneMuseumCardView(viewGroup.getContext())); default: throw new IllegalArgumentException(String.format("Unexpected viewType: %d", viewType)); } } @Override public int getItemViewType(int position) { if (items == null || items.size() < position) { throw new IllegalArgumentException("Wrong position!"); } if (items.get(position).museums.size() > 1) { return ITEM_TYPE_MANY_MUSEUMS; } else if (items.get(position).museums.size() == 1){ return ITEM_TYPE_ONE_MUSEUM; } throw new IllegalArgumentException("Wrong number of museums!"); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ((IItemDisplayer<City>) holder.itemView).displayItem(items.get(position)); } @Override public int getItemCount() { return items.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); } } }

He subido este proyecto a mi Dropbox. ¡No dudes en echarle un vistazo ! Espero eso ayude.


Intente configurar la altura de RecyclerView cuando tenga solo un elemento o más. Consulte este tema para hacer eso. Cuando tenga solo un elemento, configure RecyclerView en WRAP_CONTENT . Y cuando tenga más un elemento, configure RecyclerView en MATCH_CONTENT . ¡Buena suerte!