Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Cómo agregar divisores y espacios entre los elementos de RecyclerView?

Este es un ejemplo de cómo podría haber sido hecho anteriormente en la clase ListView , utilizando los parámetros divider y dividerHeight :

 <ListView android:id="@+id/activity_home_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@android:color/transparent" android:dividerHeight="8dp"/> 

Sin embargo, no veo tal posibilidad en la clase RecyclerView .

 <android.support.v7.widget.RecyclerView android:id="@+id/activity_home_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/> 

En ese caso, ¿está bien definir márgenes y / o añadir una vista divisoria personalizada directamente en el diseño de un elemento de lista o hay una mejor manera de lograr mi objetivo?

30 Solutions collect form web for “¿Cómo agregar divisores y espacios entre los elementos de RecyclerView?”

Actualización de octubre de 2016

La versión 25.0.0 de la Biblioteca de soporte de Android introdujo la clase DividerItemDecoration :

DividerItemDecoration es un RecyclerView.ItemDecoration que se puede utilizar como un divisor entre los elementos de un LinearLayoutManager. Soporta las orientaciones HORIZONTAL y VERTICAL.

Uso:

 DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), layoutManager.getOrientation()); recyclerView.addItemDecoration(dividerItemDecoration); 

Respuesta anterior

Algunas respuestas usan métodos que han quedado obsoletos o no ofrecen una solución completa, así que intenté hacer un resumen corto y actualizado.


A diferencia de ListView , la clase RecyclerView no tiene parámetros relacionados con el divisor. En su lugar, debe extender ItemDecoration , una clase interna de RecyclerView :

Un ItemDecoration permite que la aplicación agregue un dibujo especial y un desplazamiento de diseño a las vistas de elementos específicos del conjunto de datos del adaptador. Esto puede ser útil para dibujar divisiones entre elementos, aspectos destacados, límites de agrupación visual y más.

Todas las descripciones de artículo se dibujan en el orden en que se agregaron, antes de las vistas de elemento (en onDraw ()) y después de los elementos (en onDrawOver (Canvas, RecyclerView, RecyclerView.State).

Espaciado vertical ItemDecoration

Extiende ItemDecoration , agrega un constructor personalizado que toma la altura del espacio como un parámetro y reemplaza el método getItemOffsets() :

 public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration { private final int verticalSpaceHeight; public VerticalSpaceItemDecoration(int verticalSpaceHeight) { this.verticalSpaceHeight = verticalSpaceHeight; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.bottom = verticalSpaceHeight; } } 

Si no desea insertar espacio debajo del último elemento, agregue la condición siguiente:

 if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) { outRect.bottom = verticalSpaceHeight; } 

Nota: también puede modificar las outRect.top , outRect.left y outRect.right para el efecto deseado.

Divisor de ItemDecoration

Extienda el ItemDecoration y el ItemDecoration override onDraw() :

 public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable divider; /** * Default divider will be used */ public DividerItemDecoration(Context context) { final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS); divider = styledAttributes.getDrawable(0); styledAttributes.recycle(); } /** * Custom divider will be used */ public DividerItemDecoration(Context context, int resId) { divider = ContextCompat.getDrawable(context, resId); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); } } } 

Puede llamar al primer constructor que utilice los atributos predeterminados del divisor de Android, o el segundo que utilice su propio dibujable, por ejemplo drawable / divider.xml

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <size android:height="1dp" /> <solid android:color="#ff992900" /> </shape> 

Nota: si desea que el divisor se onDrawOver() sobre sus elementos, onDrawOver() método onDrawOver() lugar.

Uso

Para usar su nueva clase, añada VerticalSpaceItemDecoration o DividerSpaceItemDecoration a RecyclerView , por ejemplo, en el método onCreateView() su fragmento:

 private static final int VERTICAL_ITEM_SPACE = 48; private RecyclerView recyclerView; private LinearLayoutManager linearLayoutManager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_feed, container, false); recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_home_recycler_view); linearLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(linearLayoutManager); //add ItemDecoration recyclerView.addItemDecoration(new VerticalSpaceItemDecoration(VERTICAL_ITEM_SPACE)); //or recyclerView.addItemDecoration(new DividerItemDecoration(getActivity())); //or recyclerView.addItemDecoration( new DividerItemDecoration(getActivity(), R.drawable.divider)); recyclerView.setAdapter(...); return rootView; } 

Hay también la biblioteca de Lucas Rocha que se supone para simplificar el proceso de la decoración del artículo. No lo he probado aunque.

Entre sus características se encuentran:

  • Una colección de decoraciones de artículos comunes incluyendo:
  • Espaciado de artículos Divisores horizontales / verticales.
  • Producto en la lista

¿Puedo dirigir su atención a este archivo particular en Github por Alex Fu: https://gist.github.com/alexfu/0f464fc3742f134ccd1e

Es el archivo de ejemplo DividerItemDecoration.java "extraído directamente de las demostraciones de soporte". ( https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )

Fui capaz de obtener líneas de división muy bien después de importar este archivo en mi proyecto y añadirlo como decoración de un elemento a la vista de reciclador.

Así es como se ve mi onCreateView en mi fragmento que contiene el Recyclerview:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_recycler_view, container, false); mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view); mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST)); mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(getActivity()); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setItemAnimator(new DefaultItemAnimator()); return rootView; } 

Estoy seguro de estilo adicional se puede hacer, pero es un punto de partida. 🙂

ItemDecoration simple de ItemDecoration para espacios iguales entre todos los elementos.

 public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int space; public SpacesItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = space; outRect.right = space; outRect.bottom = space; // Add top margin only for the first item to avoid double space between items if(parent.getChildAdapterPosition(view) == 0) { outRect.top = space; } } } 

El simple es fijar el color de fondo para RecyclerView y diverso color de fondo para los artículos. Aquí hay un ejemplo …

 <android.support.v7.widget.RecyclerView android:background="#ECEFF1" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical"/> 

Y el elemento TextView (puede ser cualquier cosa sin embargo) con el margen inferior "x" dp o px.

 <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="1dp" android:background="#FFFFFF"/> 

La salida …

Introduzca aquí la descripción de la imagen

Solo agrega

 recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); 

También puede ser necesario agregar la dependencia
compile 'com.android.support:recyclerview-v7:25.3.1'

EDITAR:

Para personalizarlo un poco puede agregar un dibujable personalizado:

 DividerItemDecoration itemDecorator = new DividerItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); itemDecorator.setDrawable(getResources().getDrawable(R.drawable.divider)); 

Usted es libre de usar cualquier costumbre dibujable, por ejemplo:

 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary"/> <size android:height="0.5dp"/> </shape> 

Creo que el uso de divisor simple le ayudará

Para agregar divisor a cada elemento:
1- Añada esto al directorio dibujable line_divider.xml

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <size android:width="1dp" android:height="1dp" /> <solid android:color="#999999" /> </shape> 

2- Crear la clase SimpleDividerItemDecoration
Utilicé este ejemplo para definir esta clase:
https://gist.github.com/polbins/e37206fbc444207c0e92

 package com.example.myapp; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.support.v7.widget.RecyclerView; import android.view.View; import com.example.myapp.R; public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration{ private Drawable mDivider; public SimpleDividerItemDecoration(Resources resources) { mDivider = resources.getDrawable(R.drawable.line_divider); } public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } } 

3- En la actividad o fragmento que utiliza RecyclerView, dentro de onCreateView agrega esto:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RecyclerView myRecyclerView = (RecyclerView) layout.findViewById(R.id.my_recycler_view); myRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getResources())); .... } 

4- Para añadir el espacio entre los elementos
Sólo tiene que agregar la propiedad de relleno a la vista de artículo

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="4dp" > ..... item structure </RelativeLayout> 

Como he fijado ItemAnimators . El ItemDecorator no entra ni sale junto con la animación.

Simplemente terminé en tener una línea de vista en mi archivo de diseño de vista de artículo de cada elemento. Resolvió mi caso. DividerItemDecoration sentía a gran parte de la brujería para un divisor simple. O podría estar perdiendo su uso real.

 <View android:layout_width="match_parent" android:layout_height="1px" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:background="@color/lt_gray"/> 

Dado que no hay forma correcta de implementar esto correctamente utilizando Material Design, solo hice el siguiente truco para añadir un divisor directamente al elemento de lista:

 <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/dividerColor"/> 

OCTUBRE 2016 ACTUALIZACIÓN

Con la biblioteca de soporte v25.0.0 finalmente hay una implementación por defecto de los divisores horizontales y verticales básicos disponibles!

https://developer.android.com/reference/android/support/v7/widget/DividerItemDecoration.html

Esto no soluciona realmente el problema, pero como una solución temporal, puede establecer la propiedad useCompatPadding en la tarjeta en su diseño XML para que se mida igual que en las versiones anteriores a Lollipop.

 card_view:cardUseCompatPadding="true" 

Para aquellos que buscan sólo espacios entre los elementos en el RecyclerView ver mi enfoque donde se obtienen espacios iguales entre todos los elementos, excepto en el primero y el último elementos donde me dio un relleno más grande. Sólo aplico relleno a izquierda / derecha en LayoutManager horizontal y arriba / abajo en LayoutManager vertical.

 public class PaddingItemDecoration extends RecyclerView.ItemDecoration { private int mPaddingPx; private int mPaddingEdgesPx; public PaddingItemDecoration(Activity activity) { final Resources resources = activity.getResources(); mPaddingPx = (int) resources.getDimension(R.dimen.paddingItemDecorationDefault); mPaddingEdgesPx = (int) resources.getDimension(R.dimen.paddingItemDecorationEdge); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); final int itemPosition = parent.getChildAdapterPosition(view); if (itemPosition == RecyclerView.NO_POSITION) { return; } int orientation = getOrientation(parent); final int itemCount = state.getItemCount(); int left = 0; int top = 0; int right = 0; int bottom = 0; /** HORIZONTAL */ if (orientation == LinearLayoutManager.HORIZONTAL) { /** all positions */ left = mPaddingPx; right = mPaddingPx; /** first position */ if (itemPosition == 0) { left += mPaddingEdgesPx; } /** last position */ else if (itemCount > 0 && itemPosition == itemCount - 1) { right += mPaddingEdgesPx; } } /** VERTICAL */ else { /** all positions */ top = mPaddingPx; bottom = mPaddingPx; /** first position */ if (itemPosition == 0) { top += mPaddingEdgesPx; } /** last position */ else if (itemCount > 0 && itemPosition == itemCount - 1) { bottom += mPaddingEdgesPx; } } if (!isReverseLayout(parent)) { outRect.set(left, top, right, bottom); } else { outRect.set(right, bottom, left, top); } } private boolean isReverseLayout(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); return layoutManager.getReverseLayout(); } else { throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager."); } } private int getOrientation(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); return layoutManager.getOrientation(); } else { throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager."); } } } 

Dimens.xml

 <resources> <dimen name="paddingItemDecorationDefault">10dp</dimen> <dimen name="paddingItemDecorationEdge">20dp</dimen> </resources> 

Bifurqué el DividerItemDecoration de un gist más viejo y lo simplifiqué para caber mi caso de uso, y también lo modifiqué para dibujar los divisores la manera que se dibujan en ListView, incluyendo un divisor después del último artículo de la lista. Esto también manejará animaciones verticales ItemAnimator:

1) Agregue esta clase a su proyecto:

 public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable divider; public DividerItemDecoration(Context context) { try { final TypedArray a = context.obtainStyledAttributes(ATTRS); divider = a.getDrawable(0); a.recycle(); } catch (Resources.NotFoundException e) { // TODO Log or handle as necessary. } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (divider == null) return; if (parent.getChildAdapterPosition(view) < 1) return; if (getOrientation(parent) == LinearLayoutManager.VERTICAL) outRect.top = divider.getIntrinsicHeight(); else throw new IllegalArgumentException("Only usable with vertical lists"); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (divider == null) { super.onDrawOver(c, parent, state); return; } final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; ++i) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int size = divider.getIntrinsicHeight(); final int top = (int) (child.getTop() - params.topMargin - size + child.getTranslationY()); final int bottom = top + size; divider.setBounds(left, top, right, bottom); divider.draw(c); if (i == childCount - 1) { final int newTop = (int) (child.getBottom() + params.bottomMargin + child.getTranslationY()); final int newBottom = newTop + size; divider.setBounds(left, newTop, right, newBottom); divider.draw(c); } } } private int getOrientation(RecyclerView parent) { if (!(parent.getLayoutManager() instanceof LinearLayoutManager)) throw new IllegalStateException("Layout manager must be an instance of LinearLayoutManager"); return ((LinearLayoutManager) parent.getLayoutManager()).getOrientation(); } } 

2) Añade el decorador a tu RecylerView:

 recyclerView.addItemDecoration(new DividerItemDecoration(getActivity())); 

Añadir un margen a su vista, funcionó para mí.

 android:layout_marginTop="10dp" 

Si sólo desea añadir el mismo espaciado y desea hacerlo en XML , sólo ajuste el padding a su RecyclerView y la misma cantidad de layoutMargin al elemento que infla en su RecyclerView y deje que el color de fondo determine el color de espaciado.

  • Aquí está simple hack para añadir divisor
  • Simplemente agregue un fondo a la disposición de su elemento de reciclaje como sigue

     <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/shape_border" android:gravity="center" android:orientation="horizontal" android:padding="5dp" > <ImageView android:id="@+id/imageViewContactLogo" android:layout_width="60dp" android:layout_height="60dp" android:layout_marginRight="10dp" android:src="@drawable/ic_user" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.92" android:gravity="center|start" android:orientation="vertical" > <TextView android:id="@+id/textViewContactName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/textViewStatusOrNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:singleLine="true" android:text="" android:textAppearance="?android:attr/textAppearanceMedium"/> </LinearLayout> <TextView android:id="@+id/textViewUnreadCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:padding="5dp" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/red" android:textSize="22sp" /> <Button android:id="@+id/buttonInvite" android:layout_width="54dp" android:layout_height="wrap_content" android:background="@drawable/ic_add_friend" /> </LinearLayout> 

Crear siguiente shape_border.xml en la carpeta dibujable.

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:angle="270" android:centerColor="@android:color/transparent" android:centerX="0.01" android:startColor="#000" /> </shape> 

Aquí está el resultado final – un RecyclerView con divisor.

Aquí está el resultado final: una vista de reciclador con divisor

Tomado de una búsqueda de Google, añada este ItemDecoration a su RecyclerView :

 public class DividerItemDecoration extends RecyclerView.ItemDecoration { private Drawable mDivider; private boolean mShowFirstDivider = false; private boolean mShowLastDivider = false; public DividerItemDecoration(Context context, AttributeSet attrs) { final TypedArray a = context .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider}); mDivider = a.getDrawable(0); a.recycle(); } public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider, boolean showLastDivider) { this(context, attrs); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; } public DividerItemDecoration(Drawable divider) { mDivider = divider; } public DividerItemDecoration(Drawable divider, boolean showFirstDivider, boolean showLastDivider) { this(divider); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (mDivider == null) { return; } if (parent.getChildPosition(view) < 1) { return; } if (getOrientation(parent) == LinearLayoutManager.VERTICAL) { outRect.top = mDivider.getIntrinsicHeight(); } else { outRect.left = mDivider.getIntrinsicWidth(); } } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mDivider == null) { super.onDrawOver(c, parent, state); return; } // Initialization needed to avoid compiler warning int left = 0, right = 0, top = 0, bottom = 0, size; int orientation = getOrientation(parent); int childCount = parent.getChildCount(); if (orientation == LinearLayoutManager.VERTICAL) { size = mDivider.getIntrinsicHeight(); left = parent.getPaddingLeft(); right = parent.getWidth() - parent.getPaddingRight(); } else { //horizontal size = mDivider.getIntrinsicWidth(); top = parent.getPaddingTop(); bottom = parent.getHeight() - parent.getPaddingBottom(); } for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getTop() - params.topMargin; bottom = top + size; } else { //horizontal left = child.getLeft() - params.leftMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } // show last divider if (mShowLastDivider && childCount > 0) { View child = parent.getChildAt(childCount - 1); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getBottom() + params.bottomMargin; bottom = top + size; } else { // horizontal left = child.getRight() + params.rightMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private int getOrientation(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); return layoutManager.getOrientation(); } else { throw new IllegalStateException( "DividerItemDecoration can only be used with a LinearLayoutManager."); } } } 

Podemos decorar los elementos utilizando varios decoradores adjuntos a la recyclerview como el DividerItemDecoration:

Simplemente utilice lo siguiente … tomado de la respuesta de EyesClear

 public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable mDivider; /** * Default divider will be used */ public DividerItemDecoration(Context context) { final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS); mDivider = styledAttributes.getDrawable(0); styledAttributes.recycle(); } /** * Custom divider will be used */ public DividerItemDecoration(Context context, int resId) { mDivider = ContextCompat.getDrawable(context, resId); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } 

} Y luego usar lo anterior como sigue

 RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST); recyclerView.addItemDecoration(itemDecoration); 

Esto mostrará divisores entre cada elemento dentro de la lista como se muestra a continuación:

Introduzca aquí la descripción de la imagen

Y para aquellos de los que están buscando más detalles puede consultar esta guía Usando el RecyclerView _ CodePath Android Cliffnotes

Algunas respuestas aquí sugieren el uso de márgenes, pero la captura es la siguiente: Si se añaden márgenes superior e inferior, aparecerán tanto añadidos entre los elementos y serán demasiado grandes. If you only add either, there will be no margin either at the top or the bottom of the whole list. If you add half of the distance at the top, half at the bottom, the outer margins will be too small.

Thus, the only aesthetically correct solution is the divider that the system knows where to apply properly: between items but not above or below items.

Please let me know of any doubts in the comments below 🙂

If anyone is looking to only add, say, 10dp spacing between items, you can do so by setting a drawable to DividerItemDecoration :

 DividerItemDecoration dividerItemDecoration = new DividerItemDecoration( recyclerView.getContext(), layoutManager.getOrientation() ); dividerItemDecoration.setDrawable( ContextCompat.getDrawable(getContext(), R.drawable.divider_10dp) ); 

Where divider_10dp is a drawable resource containing:

 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <size android:height="10dp"/> <solid android:color="@android:color/transparent"/> </shape> 

If you want to add same space for items, the simplest way is to add top+left padding for RecycleView and right+bottom margins to card items.

dimens.xml

 <resources> <dimen name="divider">1dp</dimen> </resources> 

list_item.xml

 <CardView android:layout_marginBottom="@dimen/divider" android:layout_marginRight="@dimen/divider"> ... </CardView> 

list.xml

 <RecyclerView android:paddingLeft="@dimen/divider" android:paddingTop="@dimen/divider" /> 

This link worked like a charm for me:

https://gist.github.com/lapastillaroja/858caf1a82791b6c1a36

 import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; public class DividerItemDecoration extends RecyclerView.ItemDecoration { private Drawable mDivider; private boolean mShowFirstDivider = false; private boolean mShowLastDivider = false; public DividerItemDecoration(Context context, AttributeSet attrs) { final TypedArray a = context .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider}); mDivider = a.getDrawable(0); a.recycle(); } public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider, boolean showLastDivider) { this(context, attrs); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; } public DividerItemDecoration(Drawable divider) { mDivider = divider; } public DividerItemDecoration(Drawable divider, boolean showFirstDivider, boolean showLastDivider) { this(divider); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (mDivider == null) { return; } if (parent.getChildPosition(view) < 1) { return; } if (getOrientation(parent) == LinearLayoutManager.VERTICAL) { outRect.top = mDivider.getIntrinsicHeight(); } else { outRect.left = mDivider.getIntrinsicWidth(); } } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mDivider == null) { super.onDrawOver(c, parent, state); return; } // Initialization needed to avoid compiler warning int left = 0, right = 0, top = 0, bottom = 0, size; int orientation = getOrientation(parent); int childCount = parent.getChildCount(); if (orientation == LinearLayoutManager.VERTICAL) { size = mDivider.getIntrinsicHeight(); left = parent.getPaddingLeft(); right = parent.getWidth() - parent.getPaddingRight(); } else { //horizontal size = mDivider.getIntrinsicWidth(); top = parent.getPaddingTop(); bottom = parent.getHeight() - parent.getPaddingBottom(); } for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getTop() - params.topMargin; bottom = top + size; } else { //horizontal left = child.getLeft() - params.leftMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } // show last divider if (mShowLastDivider && childCount > 0) { View child = parent.getChildAt(childCount - 1); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getBottom() + params.bottomMargin; bottom = top + size; } else { // horizontal left = child.getRight() + params.rightMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private int getOrientation(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); return layoutManager.getOrientation(); } else { throw new IllegalStateException( "DividerItemDecoration can only be used with a LinearLayoutManager."); } } } 

Then in your activity:

 mCategoryRecyclerView.addItemDecoration( new DividerItemDecoration(this, null)); 

Or this if you are using a fragment:

 mCategoryRecyclerView.addItemDecoration( new DividerItemDecoration(getActivity(), null)); 

I have added a line in list item like below

 <View android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1px" android:background="@color/dividerColor"/> 

1px will draw the thin line.

If you want to hide the divider for the last row then divider.setVisiblity(View.GONE); on the onBindViewHolder for the last list Item.

You can add with programaticly easily.

If your Layout Manager is Linearlayout then you can use:

DividerItemDecoration is a RecyclerView.ItemDecoration that can be used as a divider between items of a LinearLayoutManager. It supports both HORIZONTAL and VERTICAL orientations.

  mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), mLayoutManager.getOrientation()); recyclerView.addItemDecoration(mDividerItemDecoration); 

fuente

 public class CommonItemSpaceDecoration extends RecyclerView.ItemDecoration { private int mSpace = 0; private boolean mVerticalOrientation = true; public CommonItemSpaceDecoration(int space) { this.mSpace = space; } public CommonItemSpaceDecoration(int space, boolean verticalOrientation) { this.mSpace = space; this.mVerticalOrientation = verticalOrientation; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.top = SizeUtils.dp2px(view.getContext(), mSpace); if (mVerticalOrientation) { if (parent.getChildAdapterPosition(view) == 0) { outRect.set(0, SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace)); } else { outRect.set(0, 0, 0, SizeUtils.dp2px(view.getContext(), mSpace)); } } else { if (parent.getChildAdapterPosition(view) == 0) { outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, 0, 0); } else { outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace), 0); } } } } 

This will add space in every item's top and bottom(or left and right).Then you can set it to your recyclerView.

 recyclerView.addItemDecoration(new CommonItemSpaceDecoration(16)); 

SizeUtils.java

 public class SizeUtils { public static int dp2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } } 

A really easy solution is to use RecyclerView-FlexibleDivider

Add dependency:

 compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' 

Add to your recyclerview:

 recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(context).build()); 

¡Y tu estas listo!

1.One of the Way is by using cardview and recycler view together we can easily add effect like divider. ex. https://developer.android.com/training/material/lists-cards.html

2.and other is by adding view as divider to list_item_layout of recycler view .

  <View android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorAccent" /> 

Implement its own version of RecyclerView.ItemDecoration

 public class SpacingItemDecoration extends RecyclerView.ItemDecoration { private int spacingPx; private boolean addStartSpacing; private boolean addEndSpacing; public SpacingItemDecoration(int spacingPx) { this(spacingPx, false, false); } public SpacingItemDecoration(int spacingPx, boolean addStartSpacing, boolean addEndSpacing) { this.spacingPx = spacingPx; this.addStartSpacing = addStartSpacing; this.addEndSpacing = addEndSpacing; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (spacingPx <= 0) { return; } if (addStartSpacing && parent.getChildLayoutPosition(view) < 1 || parent.getChildLayoutPosition(view) >= 1) { if (getOrientation(parent) == LinearLayoutManager.VERTICAL) { outRect.top = spacingPx; } else { outRect.left = spacingPx; } } if (addEndSpacing && parent.getChildAdapterPosition(view) == getTotalItemCount(parent) - 1) { if (getOrientation(parent) == LinearLayoutManager.VERTICAL) { outRect.bottom = spacingPx; } else { outRect.right = spacingPx; } } } private int getTotalItemCount(RecyclerView parent) { return parent.getAdapter().getItemCount(); } private int getOrientation(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { return ((LinearLayoutManager) parent.getLayoutManager()).getOrientation(); } else { throw new IllegalStateException("SpacingItemDecoration can only be used with a LinearLayoutManager."); } } } 

The RecyclerView is a bit different from the ListView . Actually, the RecyclerView needs a ListView like structure in it. For example, a LinearLayout . The LinearLayout has parameters for the dividing each element. In the code below I have a RecyclerView comprised of CardView objects within a LinearLayout with a "padding" that will put some space between items. Make that space really small and you get a line.

Here's the Recycler view in recyclerview_layout.xml

 <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:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".ToDoList"> <!-- A RecyclerView with some commonly used attributes --> <android.support.v7.widget.RecyclerView android:id="@+id/todo_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> 

And here is what each item looks like (and it shows as divided due to the android:padding in the LinearLayout that surrounds everything.) in another file: cards_layout.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" **android:padding="@dimen/activity_vertical_margin"**> <!-- A CardView that contains a TextView --> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="100dp" android:elevation="30dp" card_view:cardElevation="3dp"> <TextView android:id="@+id/info_text" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v7.widget.CardView> </LinearLayout> 

Too Late but for GridLayoutManager I use this:

 public class GridSpacesItemDecoration : RecyclerView.ItemDecoration { private int space; public GridSpacesItemDecoration(int space) { this.space = space; } public override void GetItemOffsets(Android.Graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { var position = parent.GetChildLayoutPosition(view); /// Only for GridLayoutManager Layouts var manager = parent.GetLayoutManager() as GridLayoutManager; if (parent.GetChildLayoutPosition(view) < manager.SpanCount) outRect.Top = space; if (position % 2 != 0) { outRect.Right = space; } outRect.Left = space; outRect.Bottom = space; } } 

This work for any span count you have.

Ollie.

I have a very simple way of adding a divider in RecyclerView. Use a custom adapter to modify the recycler view layout and then along with the recycler view items add LinearLayout with a background color (which will be the divider color) and add a height of 1dp (or as per your requirement) and width to match parent.

Aquí hay un código de ejemplo.

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="18dp"> <TextView android:id="@+id/list_row_SNO" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight=".8" android:layout_gravity="end" android:text="44." android:textAlignment="center" android:textSize="24sp" android:textColor="@color/colorBlack" android:fontFamily="sans-serif-condensed" /> <TextView android:id="@+id/list_row_Heading" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight=".2" android:layout_gravity="start" android:text="Student's application for leave and this what" android:textAlignment="textStart" android:textSize="24sp" android:textColor="@color/colorBlack" android:fontFamily="sans-serif-condensed" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorHighlight"> </LinearLayout> 

 public class VerticalItemDecoration extends RecyclerView.ItemDecoration { private boolean verticalOrientation = true; private int space = 10; public VerticalItemDecoration(int value, boolean verticalOrientation) { this.space = value; this.verticalOrientation = verticalOrientation; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //skip first item in the list if (parent.getChildAdapterPosition(view) != 0) { if (verticalOrientation) { outRect.set(space, 0, 0, 0); } else if (!verticalOrientation) { outRect.set(0, space, 0, 0); } } } } 

 mCompletedShippingRecyclerView.addItemDecoration(new VerticalItemDecoration(20,false)); 

Here's my lazy approach but it works: wrap the CardView in a layout and set a padding/margin on the parent layout to mimic the divider, and force the normal divider to null

list_item.xml

 <LinearLayout android:id="@+id/entry_item_layout_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="<divider_size>" > // this is the divider <CardView android:layout_width="<width_size>" android:layout_height="<height_size>"> ... </CardView> </LinearLayout 

list.xml

 <RecyclerView android:divider="@null" android:layout_width="<width_size>" android:layout_height="<height_size>" ... /> 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.