如何在RecyclerView中的项目之间添加分隔符和空格?
这是一个如何在ListView
类中使用divider和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"/>
但是,在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"/>
在这种情况下,定义边距和/或直接将自定义分隔视图添加到列表项的布局是否可行,还是有更好的方法来实现我的目标?
2016年10月更新
Android支持库版本25.0.0引入了DividerItemDecoration
类:
DividerItemDecoration是一个RecyclerView.ItemDecoration,可用作LinearLayoutManager项目之间的分隔符。 它支持HORIZONTAL和VERTICAL方向。
用法:
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), layoutManager.getOrientation()); recyclerView.addItemDecoration(dividerItemDecoration);
以前的答案
有些答案要么使用已经过时的方法,要么不提供完整的解决方案,所以我试图做一个简短的,最新的总结。
与ListView
不同的是, RecyclerView
类没有与divider相关的参数。 相反,你需要扩展一个RecyclerView
的内部类ItemDecoration
:
ItemDecoration允许应用程序从适配器的数据集中为特定的项目视图添加一个特殊的图形和布局偏移量。 这可以用于在项目之间绘制分隔线,突出显示,视觉分组边界等等。
所有ItemDecorations按照它们在项目视图之前(onDraw())和项目之后(onDrawOver(Canvas,RecyclerView,RecyclerView.State))的添加顺序绘制。
垂直间距ItemDecoration
扩展ItemDecoration
,添加以空间高度作为参数的自定义构造函数并覆盖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; } }
如果您不想在最后一项下插入空格,请添加以下条件:
if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) { outRect.bottom = verticalSpaceHeight; }
注意:您也可以修改outRect.top
, outRect.left
和outRect.right
属性以获得所需的效果。
Divider ItemDecoration
扩展ItemDecoration
并覆盖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); } } }
您可以调用使用默认Android分隔符属性的第一个构造函数,或者使用您自己的可绘制的第二个构造函数,例如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>
注意:如果您希望将分隔线绘制在您的项目上,请onDrawOver()
方法。
用法
要使用新类,请将VerticalSpaceItemDecoration
或DividerSpaceItemDecoration
添加到RecyclerView
,例如在片段的onCreateView()
方法中:
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; }
还有卢卡斯·罗查的图书馆 ,这应该是简化项目装修过程。 还没有尝试过。
其特点是:
- 库存物品装饰的集合包括:
- 项目间隔水平/垂直分隔符。
- 列表项目
我可以直接把你的注意力放在Github上的Alex Fu上: https : //gist.github.com/alexfu/0f464fc3742f134ccd1e
这是DividerItemDecoration.java示例文件“直接从支持演示中拉出”( https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )
在我的项目中导入此文件后,我能够很好地获得分隔线,并将其作为项目装饰添加到回收站视图中。
以下是我的onCreateView在包含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; }
我相信可以做更多的造型,但这是一个起点。 🙂
简单ItemDecoration
实现所有项目之间相等的空格。
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; } } }
只需添加
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL));
此外,您可能需要添加依赖项
compile 'com.android.support:recyclerview-v7:26.0.1'
编辑:
为了自定义一点,你可以添加一个自定义绘图:
DividerItemDecoration itemDecorator = new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL); itemDecorator.setDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.divider));
您可以自由使用任何自定义drawable,例如:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary"/> <size android:height="0.5dp"/> </shape>
简单的是为RecyclerView设置背景颜色,为项目设置不同的背景颜色。 这是一个例子…
<android.support.v7.widget.RecyclerView android:background="#ECEFF1" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical"/>
和TextView的项目(它可以是任何东西)与下边距“x”dp或px。
<TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="1dp" android:background="#FFFFFF"/>
输出 …
我认为使用简单的分频器将帮助你
为每个项目添加分隔符:
1-将其添加到可绘制目录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-创建SimpleDividerItemDecoration类
我用这个例子来定义这个类:
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-在使用RecyclerView的活动或片段中,在onCreateView内添加:
@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-添加项目之间的间距
你只需要添加填充属性到你的项目视图
<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>
正如我设置ItemAnimators
。 ItemDecorator
不会与动画一起进入或退出。
我只是最终在每个项目的项目视图布局文件中有一个视图行。 它解决了我的情况。 DividerItemDecoration
觉得是一个简单的分隔符的巫术。 或者我可能会错过它的真正用途。
<View android:layout_width="match_parent" android:layout_height="1px" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:background="@color/lt_gray"/>
由于没有正确的方法来实现这个,但正确使用材料设计,我只是做了以下诀窍直接添加一个分隔列表项:
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/dividerColor"/>
2016年10月更新
随着支持库v25.0.0最终是基本的水平和垂直分频器的默认实现!
https://developer.android.com/reference/android/support/v7/widget/DividerItemDecoration.html
这实际上并不能解决问题,但是作为一个临时解决方法,您可以在XML布局中的卡上设置useCompatPadding属性,使其与在Lollipop版本之前的版本相同。
card_view:cardUseCompatPadding="true"
对于那些正在寻找RecyclerView
物品之间的空间的人,请参阅我的方法,在所有物品之间获得相同的空间,除了在第一个和最后一个物品之间给予更大的填充。 我只在水平LayoutManager
向左/向右应用填充,在垂直LayoutManager
向上/向下应用填充。
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>
我把DividerItemDecoration从一个较老的要点中分出来,并将其简化以适应我的用例,并且我也修改了它以在ListView中绘制分隔符的方式,包括最后一个列表项之后的分隔符。 这也将处理垂直ItemAnimator动画:
1)将这个类添加到你的项目中:
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)添加装饰到你的RecylerView:
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
为您的视图添加保证金,它为我工作。
android:layout_marginTop="10dp"
如果你只是想添加相等的间距,并希望在XML中做到这一点,只需将padding
设置为您的RecyclerView
并将等量的layoutMargin
设置为您膨胀到RecyclerView
的项目,然后让背景颜色确定间距颜色。
- 这里是简单的黑客添加分频器
-
只需添加一个背景到您的回收站项目的布局如下
<?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>
在drawable文件夹中创建以下shape_border.xml
<?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>
这是最后的结果 – 一个带分隔符的RecyclerView。
采取从谷歌搜索,添加此ItemDecoration到您的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."); } } }
我们可以使用附加到recyclerview的各种装饰器来修饰项目,比如DividerItemDecoration:
只需使用以下…从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); } }
}然后使用上面的如下
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST); recyclerView.addItemDecoration(itemDecoration);
这将在列表中的每个项目之间显示分隔符,如下所示:
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 🙂
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);
资源
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());
And you're done!
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.
1.One of the Way is by using cardview and recycler view together we can easily add effect like divider. 恩。 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>
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.
这是一个示例代码。
<?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));
This is simple, you don't need such complicated code
DividerItemDecoration divider = new DividerItemDecoration(mRVMovieReview.getContext(), DividerItemDecoration.VERTICAL); divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.line_divider)); mRVMovieReview.addItemDecoration(divider);
Add this in your drawable : 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:height="1dp" /> <solid android:color="@android:color/black" /> </shape>
- ClassCastException android.widget.FrameLayout $ LayoutParams to android.support.v4.widget.DrawerLayout $ LayoutParams
- 尝试在Android中创build文件:打开失败:EROFS(只读文件系统)
- 用Lint和SonarQube分析Android项目
- XML呈现错误Android预览N
- 将可绘制的资源图像转换成位图
- 在Android中保存和读取来自内部存储器的位图/图像
- 发送一个意图浏览器打开特定的URL
- 适用于Android的全屏Web应用程序
- Android的片段 – 如何保存片段中的视图的状态,当另一个片段被推上它的顶部