Reputation: 2669
I am developing an android application where I am using RecyclerView
. I need to add a divider in RecyclerView
.
I tried to add -
recyclerView.addItemDecoration(new
DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL_LIST));
below is my xml code -
<android.support.v7.widget.RecyclerView
android:id="@+id/drawerList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
/>
Upvotes: 264
Views: 259361
Reputation: 27545
The Right way is to define ItemDecoration
for the RecyclerView
is as following
SimpleDividerItemDecoration.java
public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public SimpleDividerItemDecoration(Context context) {
mDivider = ContextCompat.getDrawable(context, R.drawable.line_divider);
}
@Override
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);
}
}
}
Or If you are using kotlin: SimpleDividerItemDecoration.kt
class SimpleDividerItemDecoration(context: Context, @DrawableRes dividerRes: Int) : ItemDecoration() {
private val mDivider: Drawable = ContextCompat.getDrawable(context, dividerRes)!!
override fun onDrawOver(c: Canvas, parent: RecyclerView) {
val left = parent.paddingLeft
val right = parent.width - parent.paddingRight
val childCount = parent.childCount
for (i in 0 until childCount) {
val child: View = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams
val top: Int = child.bottom + params.bottomMargin
val bottom = top + mDivider.intrinsicHeight
mDivider.setBounds(left, top, right, bottom)
mDivider.draw(c)
}
}
}
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="@color/dark_gray" />
</shape>
Finally set it like this
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(this));
As pointed out by @Alan S.
context.getResources().getDrawable(R.drawable.line_divider);
is depreciated instead of that you can use
ContextCompat.getDrawable(context,R.drawable.line_divider);
Upvotes: 249
Reputation: 2520
MaterialDividerItemDecoration from Material-IO library is a complete solution for many use cases like list item division or section division. It has everything a developer may need like insets and styling without implementing your own item decoration. This Material Divider guide + implementation is really good to check.
Upvotes: 1
Reputation: 3107
Kotlin Version:
recyclerview.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
Upvotes: 22
Reputation: 116
recyclerview.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.HORIZONTAL));
for vertical line use LinearLayoutManager.VERTICAL
Upvotes: 2
Reputation: 61
KOTLIN - If you are looking for custom color divider between recycler view items, then here is the solution which works for me:
Step 1 : Give your recycler view a default item decoration. recyclerView.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(activity, androidx.recyclerview.widget.LinearLayoutManager.VERTICAL))
Step 2 : Add a xml drawable specifying the size - width and height with the color you want.
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="@color/your_color" />
</shape>
Step 3 : Add this line in your app theme.
<item name="android:listDivider">@drawable/your_drawable</item>
Upvotes: 2
Reputation: 1675
Alright, if don't need your divider color to be changed just apply alpha to the divider decorations.
Example for GridLayoutManager with transparency:
DividerItemDecoration horizontalDividerItemDecoration = new DividerItemDecoration(WishListActivity.this,
DividerItemDecoration.HORIZONTAL);
horizontalDividerItemDecoration.getDrawable().setAlpha(50);
DividerItemDecoration verticalDividerItemDecoration = new DividerItemDecoration(WishListActivity.this,
DividerItemDecoration.VERTICAL);
verticalDividerItemDecoration.getDrawable().setAlpha(50);
my_recycler.addItemDecoration(horizontalDividerItemDecoration);
my_recycler.addItemDecoration(verticalDividerItemDecoration);
You can still change the color of dividers by just setting color filters to it.
Example for GridLayoutManager by setting tint:
DividerItemDecoration horizontalDividerItemDecoration = new DividerItemDecoration(WishListActivity.this,
DividerItemDecoration.HORIZONTAL);
horizontalDividerItemDecoration.getDrawable().setTint(getResources().getColor(R.color.colorAccent));
DividerItemDecoration verticalDividerItemDecoration = new DividerItemDecoration(WishListActivity.this,
DividerItemDecoration.VERTICAL);
verticalDividerItemDecoration.getDrawable().setAlpha(50);
my_recycler.addItemDecoration(horizontalDividerItemDecoration);
my_recycler.addItemDecoration(verticalDividerItemDecoration);
Additionally you can also try setting color filter,
horizontalDividerItemDecoration.getDrawable().setColorFilter(colorFilter);
Upvotes: 0
Reputation: 69
i think its the easiest way
mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
// or DividerItemDecoration.HORIZONTALL
mDividerItemDecoration.setDrawable(getDrawable(R.drawable.myshape));
recyclerView.addItemDecoration(mDividerItemDecoration);
Note that : myshape can be rectangel with height you want to make your divider
Upvotes: 2
Reputation: 582
Just add a View by the end of you item adapter:
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFFFFF"/>
Upvotes: 43
Reputation: 1
Bhuvanesh BS solution works. Kotlin version of this:
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import androidx.recyclerview.widget.RecyclerView
class DividerItemDecorator(private val mDivider: Drawable?) : RecyclerView.ItemDecoration() {
override fun onDraw(
canvas: Canvas,
parent: RecyclerView,
state: RecyclerView.State
) {
val dividerLeft = parent.paddingLeft
val dividerRight = parent.width - parent.paddingRight
for (i in 0 until parent.childCount - 1) {
val child = parent.getChildAt(i)
val dividerTop =
child.bottom + (child.layoutParams as RecyclerView.LayoutParams).bottomMargin
val dividerBottom = dividerTop + mDivider!!.intrinsicHeight
mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom)
mDivider.draw(canvas)
}
}
}
Upvotes: 0
Reputation: 1996
class ItemOffsetDecoration(
context: Context,
private val paddingLeft: Int,
private val paddingRight: Int
) : RecyclerView.ItemDecoration() {
private var mDivider: Drawable? = null
init {
mDivider = ContextCompat.getDrawable(context, R.drawable.divider_medium)
}
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
val left = parent.paddingLeft + paddingLeft
val right = parent.width - parent.paddingRight - paddingRight
val childCount = parent.childCount
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams
val top = child.bottom + params.bottomMargin
val bottom = top + (mDivider?.intrinsicHeight ?: 0)
mDivider?.let {
it.setBounds(left, top, right, bottom)
it.draw(c)
}
}
}
}
You just need to specify a color in R.drawable.divider_medium
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/black" />
<size
android:height="1dp"
android:width="1dp" />
</shape>
and add it to your recyclerView
recyclerView.addItemDecoration(
ItemOffsetDecoration(
this,
resources.getDimension(resources.getDimension(R.dimen.dp_70).roundToInt()).roundToInt(),
0
)
)
refernce this
Upvotes: 1
Reputation: 6425
The way how I'm handling the Divider view and also Divider Insets is by adding a RecyclerView extension.
Add a new extension file by naming View or RecyclerView:
RecyclerViewExtension.kt
and add the setDivider
extension method inside the RecyclerViewExtension.kt file.
/*
* RecyclerViewExtension.kt
* */
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
fun RecyclerView.setDivider(@DrawableRes drawableRes: Int) {
val divider = DividerItemDecoration(
this.context,
DividerItemDecoration.VERTICAL
)
val drawable = ContextCompat.getDrawable(
this.context,
drawableRes
)
drawable?.let {
divider.setDrawable(it)
addItemDecoration(divider)
}
}
Create a Drawable resource file inside of drawable
package like recycler_view_divider.xml
:
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="10dp"
android:insetRight="10dp">
<shape>
<size android:height="0.5dp" />
<solid android:color="@android:color/darker_gray" />
</shape>
</inset>
where you can specify the left and right margin on android:insetLeft
and android:insetRight
.
On your Activity or Fragment where the RecyclerView is initialized, you can set the custom drawable by calling:
recyclerView.setDivider(R.drawable.recycler_view_divider)
Cheers 🍺
Upvotes: 20
Reputation: 17895
All of these answers got me close but they were each missing a key detail. After a bit of research, I found the easiest route to be a combination of these 3 steps:
Step 1: while configuring RecyclerView
recyclerView.addItemDecoration(
new DividerItemDecoration(context, layoutManager.getOrientation()));
Step 2: in a file like res/drawable/divider_gray.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="1px" android:height="1px" />
<solid android:color="@color/gray" />
</shape>
Step 3: in the app's theme
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Other theme items above -->
<item name="android:listDivider">@drawable/divider_gray</item>
</style>
EDIT: Updated to skip last divider:
After using this a bit, I realized it was drawing a divider after the last item, which was annoying. So I modified Step 1 as follows to override that default behavior in DividerItemDecoration (of course, making a separate class is another option):
recyclerView.addItemDecoration(
new DividerItemDecoration(context, layoutManager.getOrientation()) {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
// hide the divider for the last child
if (position == parent.getAdapter().getItemCount() - 1) {
outRect.setEmpty();
} else {
super.getItemOffsets(outRect, view, parent, state);
}
}
}
);
Upvotes: 43
Reputation: 1710
So this might not be the correct way, but I just added a view to the single item view of the RecyclerView (as I don't think there is a built-in function) like so:
<View
android:layout_width="fill_parent"
android:layout_height="@dimen/activity_divider_line_margin"
android:layout_alignParentBottom="true"
android:background="@color/tasklist_menu_dividerline_grey" />
This means each item will have a line which fills it at its bottom. I made it about 1dp high with a #111111
background. This also gives it a kind of "3D" effect.
Upvotes: 8
Reputation: 101
Try this simple single line code
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),LinearLayoutManager.VERTICAL));
Upvotes: 9
Reputation: 13555
In the October 2016 update, the support library v25.0.0 now has a default implementation of basic horizontal and vertical dividers available!
https://developer.android.com/reference/android/support/v7/widget/DividerItemDecoration.html
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
Upvotes: 348
Reputation: 47
Simply add a margin of x amount at the bottom of an item in your RecycleView Adapter
.
onCreateViewHolder
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 0, 0, 5);
itemView.setLayoutParams(layoutParams);
Upvotes: 1
Reputation: 13627
You can create a simple reusable divider.
Create Divider:
public class DividerItemDecorator extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerItemDecorator(Drawable divider) {
mDivider = divider;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int dividerLeft = parent.getPaddingLeft();
int dividerRight = 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 dividerTop = child.getBottom() + params.bottomMargin;
int dividerBottom = dividerTop + mDivider.getIntrinsicHeight();
mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
mDivider.draw(canvas);
}
}
}
Create Divider 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="@color/grey_300" />
</shape>
Add divider to your Recyclerview:
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(context, R.drawable.divider));
recyclerView.addItemDecoration(dividerItemDecoration);
To remove divider for the last item:
To prevent divider drawing for the last item you have to change this line.
for (int i = 0; i < childCount; i++)
To
for (int i = 0; i < childCount-1; i++)
Your final implementation should be like this:
public class DividerItemDecorator extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerItemDecorator(Drawable divider) {
mDivider = divider;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int dividerLeft = parent.getPaddingLeft();
int dividerRight = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount - 1; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int dividerTop = child.getBottom() + params.bottomMargin;
int dividerBottom = dividerTop + mDivider.getIntrinsicHeight();
mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
mDivider.draw(canvas);
}
}
}
Hope it helps:)
Upvotes: 6
Reputation: 634
You need add next line...
mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
Upvotes: 8
Reputation: 8499
I think you are using Fragments
to have RecyclerView
Simply add these lines after creating your RecyclerView
and LayoutManager
Objects
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividerItemDecoration);
Thats it!
It supports both HORIZONTAL and VERTICAL orientations.
Upvotes: 8
Reputation: 1135
Create a seperate xml file in res/drawable folder
<?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>
Connect that xml file (your_file) at the main activity, like this:
DividerItemDecoration divider = new DividerItemDecoration(
recyclerView.getContext(),
DividerItemDecoration.VERTICAL
);
divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.your_file));
recyclerView.addItemDecoration(divider);
Upvotes: 11
Reputation: 3042
Here is the code for a simple custom divider (vertical divider / 1dp height / black ):
It suppose you have Support Library:
compile "com.android.support:recyclerview-v7:25.1.1"
java code
DividerItemDecoration divider = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.my_custom_divider));
recyclerView.addItemDecoration(divider);
then the custom_divider.xml file sample :
<?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>
Upvotes: 24
Reputation: 41
Android just makes little things too complicated unfortunately. Easiest way to achieve what you want, without implementing DividerItemDecoration here:
Add background color to the RecyclerView to your desired divider color:
<RecyclerView
android:id="@+id/rvList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/colorLightGray"
android:scrollbars="vertical"
tools:listitem="@layout/list_item"
android:background="@android:color/darker_gray"/>
Add bottom margin (android:layout_marginBottom) to the layout root of the item (list_item.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:layout_marginBottom="1dp">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="John Doe" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tvName"
android:text="Some description blah blah" />
</RelativeLayout>
This should give 1dp space between the items and the background color of RecyclerView (which is dark gray would appear as divider).
Upvotes: 4
Reputation: 1741
If you want to have both horizontal and vertical dividers:
Define horizontal & vertical divider drawables:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<size android:height="1dip" />
<solid android:color="#22000000" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<size android:width="1dip" />
<solid android:color="#22000000" />
</shape>
Add this code segment below:
DividerItemDecoration verticalDecoration = new DividerItemDecoration(recyclerview.getContext(),
DividerItemDecoration.HORIZONTAL);
Drawable verticalDivider = ContextCompat.getDrawable(getActivity(), R.drawable.vertical_divider);
verticalDecoration.setDrawable(verticalDivider);
recyclerview.addItemDecoration(verticalDecoration);
DividerItemDecoration horizontalDecoration = new DividerItemDecoration(recyclerview.getContext(),
DividerItemDecoration.VERTICAL);
Drawable horizontalDivider = ContextCompat.getDrawable(getActivity(), R.drawable.horizontal_divider);
horizontalDecoration.setDrawable(horizontalDivider);
recyclerview.addItemDecoration(horizontalDecoration);
Upvotes: 46
Reputation: 414
To make N J's answer a little simpler you can do:
public class DividerColorItemDecoration extends DividerItemDecoration {
public DividerColorItemDecoration(Context context, int orientation) {
super(context, orientation);
setDrawable(ContextCompat.getDrawable(context, R.drawable.line_divider));
}
}
Upvotes: 1
Reputation: 349
yqritc's RecyclerView-FlexibleDivider makes this a one liner. First add this to your build.gradle
:
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' // requires jcenter()
Now you can configure and add a divder where you set your recyclerView's adapter:
recyclerView.setAdapter(myAdapter);
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).color(Color.RED).sizeResId(R.dimen.divider).marginResId(R.dimen.leftmargin, R.dimen.rightmargin).build());
Upvotes: 2