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

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

  

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

  

En ese caso, ¿está bien definir los márgenes y / o agregar una vista divisoria personalizada directamente en el diseño de un elemento de la lista o hay una forma mejor de lograr mi objective?

    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 divisor entre los elementos de un LinearLayoutManager. Admite orientaciones HORIZONTALES y VERTICALES.

    Uso:

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

    Respuesta anterior

    Algunas respuestas usan métodos que desde entonces se han desaprobado o no brindan una solución completa, así que traté de hacer un resumen corto y actualizado.


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

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

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

    Espaciado vertical ItemDecoration

    Extienda ItemDecoration , agregue un constructor personalizado que tome la altura del espacio como un parámetro y anule 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 siguiente condición:

     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.

    Divider ItemDecoration

    Extienda ItemDecoration y anule el método 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 usa los atributos del separador predeterminados de Android, o al segundo que usa su propio drawable, por ejemplo drawable / divider.xml

     < ?xml version="1.0" encoding="utf-8"?>     

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

    Uso

    Para usar su nueva clase, agregue 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; } 

    También está la biblioteca de Lucas Rocha, que se supone que simplifica el proceso de decoración del artículo. No lo he probado sin embargo.

    Entre sus características se encuentran:

    • Una colección de decoraciones de artículos en inventario que incluye:
    • Espaciado entre artículos Divisores horizontales / verticales.
    • Artículo de lista

    Solo agrega

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

    También es posible que deba agregar la dependencia
    compile 'com.android.support:recyclerview-v7:27.1.0'

    EDITAR:

    Para personalizarlo un poco puedes agregar un dibujable personalizado:

     DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL); itemDecorator.setDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider)); 

    Usted es libre de utilizar cualquier dibujable personalizado, por ejemplo:

         

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

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

    Pude obtener líneas divisoras muy bien después de importar este archivo en mi proyecto y agregarlo como una decoración de elementos a la vista de reciclador.

    Así es como se ve mi onCreateView en mi fragmento que contiene 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 que se puede hacer un estilo adicional, pero es un punto de partida. 🙂

    ItemDecoration simple de ItemDecoration para espacios iguales entre todos los artículos.

     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 más simple es establecer el color de fondo para RecyclerView y diferentes colores de fondo para los elementos. Aquí hay un ejemplo …

      

    y el elemento TextView (puede ser cualquier cosa) con el margen inferior “x” dp o px.

      

    La salida …

    enter image description here

    Creo que usar un divisor simple te ayudará

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

     < ?xml version="1.0" encoding="utf-8"?>     

    2- Crear la clase SimpleDividerItemDecoration
    Usé 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 actividad o fragmento que utilizando RecyclerView, dentro deCreateView agregue 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 agregar espaciado entre los elementos
    solo necesita agregar propiedad de relleno a su vista de elemento

      ..... item structure  

    Como he establecido ItemAnimators . ItemDecorator no ingresa ni sale junto con la animación.

    Simplemente terminé teniendo una línea de vista en el archivo de diseño de vista de elemento de cada artículo. Solucionó mi caso. DividerItemDecoration sintió en gran parte de hechicería por un simple divisor. O podría estar perdiendo su uso real.

      

    Como no existe una manera correcta de implementar esto correctamente utilizando Material Design, hice el siguiente truco para agregar un divisor en el elemento de la lista directamente:

      

    ACTUALIZACIÓN DE OCTUBRE DE 2016

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

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

    Esto en realidad no resuelve el problema, pero como una solución temporal, puede establecer la propiedad useCompatPadding en la tarjeta en su diseño XML para que mida de la misma manera que en las versiones anteriores a Lollipop.

     card_view:cardUseCompatPadding="true" 

    Agregue un margen a su vista, funcionó para mí.

     android:layout_marginTop="10dp" 

    Si solo desea agregar espaciado equitativo y desea hacerlo en XML , simplemente configure el padding en su RecyclerView y la misma cantidad de layoutMargin en el elemento que infle en su RecyclerView , y permita que el color de fondo determine el color del espaciado.

    Para aquellos que buscan espacios entre los elementos de RecyclerView vean mi enfoque en el que se obtienen espacios iguales entre todos los elementos, excepto en el primero y el último ítems donde proporcioné un relleno más grande. Solo aplico relleno a la izquierda / derecha en LayoutManager horizontal y a 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

      10dp 20dp  

    Si alguien está buscando solo agregar, digamos, un espaciado de 10dp entre los elementos, puede hacerlo configurando un DividerItemDecoration a DividerItemDecoration :

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

    Donde divider_10dp es un recurso divider_10dp que contiene:

         
    • Aquí hay un truco simple para agregar divisor
    • Simplemente agregue un fondo al diseño de su artículo reciclador de la siguiente manera

       < ?xml version="1.0" encoding="utf-8"?>          

    Crea el siguiente shape_border.xml en una carpeta dibujable

      < ?xml version="1.0" encoding="utf-8"?>    

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

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

    Bifuré DividerItemDecoration de una idea anterior y lo simplifiqué para que se ajustara a mi caso de uso, y también lo modifiqué para dibujar los divisores de la misma forma en que se dibujaron en ListView, incluido un divisor después del último elemento 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) Agregue el decorador a su RecylerView:

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

    Esto es simple, no necesitas un código tan complicado

      DividerItemDecoration divider = new DividerItemDecoration(mRVMovieReview.getContext(), DividerItemDecoration.VERTICAL); divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.line_divider)); mRVMovieReview.addItemDecoration(divider); 

    Agregue esto en su dibujo: line_divider.xml

      < ?xml version="1.0" encoding="utf-8"?>     

    Tomado de una búsqueda en Google, agregue 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."); } } } 

    Si desea agregar el mismo espacio para los elementos, la forma más simple es agregar el margen superior + izquierdo para RecycleView y los márgenes derecho + inferior a los elementos de la tarjeta.

    dimens.xml

      1dp  

    list_item.xml

      ...  

    list.xml

      

    Podemos decorar los artículos usando varios decoradores adjuntos a la vista del reciclador como el DividerItemDecoration:

    Simplemente use 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); } } 

    } and then use the above as follows

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

    This will display dividers between each item within the list as shown below:

    enter image description here

    And for those of who are looking for more details can check out this guide Using the RecyclerView _ CodePath Android Cliffnotes

    Some answers here suggest the use of margins but the catch is that : If you add both top and bottom margins, they will appear both added between items and they will be too large. 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 🙂

    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

      

    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.

    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.

    You can add with progtwigticly 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

    Agregar dependencia:

     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 .

       

    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

         

    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"?>       

    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 muestra.

     < ?xml version="1.0" encoding="utf-8"?>        

     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));