A RecyclerView is nested in a CardView. I tried to call addItemDecoration() to add dividers into RecycylerView,but it didn't work.
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/white_color"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
card_view:cardElevation="3dp">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_saleproduct_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_saleproduct_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="visible" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.v7.widget.CardView>
The java code:
mSwipe = (SwipeRefreshLayout)view.findViewById(R.id.swipe_saleproduct_list);
mRecyclerView= (RecyclerView) view.findViewById(R.id.recycler_saleproduct_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(UIUtils.getContext()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(UIUtils.getContext(), DividerItemDecoration.VERTICAL_LIST));
SaleProductListAdapter saleProductListAdapter = new SaleProductListAdapter(UIUtils.getContext(), mRecyclerView, list, mSwipe);
mRecyclerView.setAdapter(saleProductListAdapter);
This below is a good example, take a look at it:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
#Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
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 top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
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 left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
#Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
And here is my Fragment, it works well, which divider is clear and thin:
public static class RecyclerViewFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_recyclerview, container, false);
RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
RecyclerViewAdapter adapter = new RecyclerViewAdapter(getActivity(), getResources()
.getStringArray(R.array.countries));
recyclerView.setAdapter(adapter);
return root;
}
}
I hope you will be inspired.
The mDivider with System maybe NullPointerException on platform KitKat and below,so I suggest use mDivider with oneself like:
public MyDecoration(Context context, int orientation) {
mDivider = context.getResources().getDrawable(R.drawable.line_divider);
setOrientation(orientation);
}
And Here is the line_divider:
<?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/color_in_common_green" />
</shape>
It maybe work well
Related
Currently my divider is only drawing one width:
How would can I add an extra divider for every increment position in my recyclerview?
Here is my ItemDecoration class:
public SimpleDivider(Context mContext, ArrayList<Integer> mDepth) {
mDivider = ContextCompat.getDrawable(mContext, R.drawable.recycler_view_divider);
this.mContext = mContext;
this.mDepth = mDepth;
dividerMargin = 15;
}
#Override
public void onDraw(#NonNull Canvas c, #NonNull RecyclerView parent, #NonNull RecyclerView.State state) {
int top = 0;
int bottom = parent.getHeight();
int childCount = parent.getChildCount();
for(int i = 0; i < childCount; ++i) {
int right = dividerMargin;
int left = 0;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
Edit1: Here's the Adapter. I thought it wouldn't be needed because all the logic would be written inside the ItemDecoration class.
private ArrayList<String> mList;
public class ViewHolder extends RecyclerView.ViewHolder{
TextView singleMessageComment;
public ViewHolder(#NonNull View itemView) {
super(itemView);
singleMessageComment = itemView.findViewById(R.id.item_child_comment);
}
}
public AdapterTest(ArrayList<String> mList) {
this.mList = mList;
}
#NonNull
#Override
public AdapterTest.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycler_view_single_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull AdapterTest.ViewHolder viewHolder, int i) {
viewHolder.singleMessageComment.setText(mList.get(i));
}
#Override
public int getItemCount() {
return mList.size();
}
Adding decorations:
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
recyclerView.addItemDecoration(new LeftDividerItemDecorator(this));
Declaration of the left divider item decorator:
public class LeftDividerItemDecorator extends RecyclerView.ItemDecoration {
private final Drawable mDivider;
private final Rect mBounds = new Rect();
private final Context mContext;
LeftDividerItemDecorator(Context context) {
mContext = context;
mDivider = context.getResources().getDrawable(R.drawable.divider);
}
public void onDraw(#NonNull Canvas c, #NonNull RecyclerView parent, #NonNull RecyclerView.State state) {
if (parent.getLayoutManager() != null && mDivider != null) {
drawLeftDivider(c, parent);
}
}
private void drawLeftDivider(Canvas canvas, RecyclerView parent) {
canvas.save();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; ++i) {
View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
int childAdapterPosition = parent.getChildAdapterPosition(child);
int left = parent.getPaddingLeft();
// Solid size according to divider.xml width
//int right = left + (mDivider.getIntrinsicWidth());
// Dynamic size according to divider.xml width multiplied by child number
int right = left + (mDivider.getIntrinsicWidth() * (childAdapterPosition + 1));
int top = child.getTop();
int bottom = child.getBottom();
// Draw left vertical divider
mDivider.setBounds(
left,
top,
right,
bottom
);
mDivider.draw(canvas);
}
canvas.restore();
}
// Handles dividers width - move current views to right
public void getItemOffsets(#NonNull Rect outRect, #NonNull View view, #NonNull RecyclerView parent, #NonNull RecyclerView.State state) {
if (mDivider == null) {
outRect.set(0, 0, 0, 0);
} else {
int childAdapterPosition = parent.getChildAdapterPosition(view);
outRect.set(mDivider.getIntrinsicWidth() * childAdapterPosition, 0, 0, 0);
}
}
}
Divider's xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="4dp"
android:height="4dp" />
<solid android:color="#color/colorAccent" />
</shape>
Preview:
I'm trying to create multiple vertical dividers for each ViewHolder in recyclerView but can't figure out how.
Heres my code for working horizontal dividers:
#Override
public void onDrawOver(#NonNull Canvas c, #NonNull RecyclerView parent, #NonNull RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int count = parent.getChildCount();
for(int i = 0; i < count; 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);
}
}
drawable divider:
<?xml version="1.0" encoding="utf-8"?>
<size
android:width="10dp"
android:height="10dp" />
<solid android:color="#color/standardBlue" />
DividerItemDecoration is a RecyclerView.ItemDecoration that can be used as a divider between items of a LinearLayoutManager. It supports both HORIZONTAL and VERTICAL orientations.
Usage:
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
Previous answer
All ItemDecorations are drawn in the order they were added, before the item views (in onDraw()) and after the items (in onDrawOver(Canvas, RecyclerView, RecyclerView.State).
Vertical spacing ItemDecoration
Extend ItemDecoration, add custom constructor which takes space height as a
parameter and override getItemOffsets() method:
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 you don't want to insert space below the last item, add the following condition:
if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) {
outRect.bottom = verticalSpaceHeight;
}
Note: you can also modify outRect.top, outRect.left and outRect.right properties for desired effect.
Divider ItemDecoration
Extend ItemDecoration and override onDraw() method:
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);
}
}
}
You can either call the first constructor that uses the default Android divider attributes, or the second one that uses your own drawable, for example 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>
Note: if you want the divider to be drawn over your items, override onDrawOver() method instead.
Usage
To use your new class add VerticalSpaceItemDecoration or DividerSpaceItemDecoration to RecyclerView, for example in your fragment's onCreateView() method:
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;
}
I need to add a divider between two NavigationViews in my app. (navigation_drawer_top and navigation_drawer_bottom).
I have tried this. But this added divider to top of the view. not at end of the first NavigationView(navigation_drawer_top).
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"/>
Here is my code
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/navigation_drawer_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start">
<android.support.design.widget.NavigationView
android:id="#+id/navigation_drawer_top"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#color/menuColor"
android:paddingLeft="50dp"
app:headerLayout="#layout/nav_header_main"
app:itemTextAppearance="#style/NavigationDrawerStyle"
app:itemTextColor="#color/menuTextColour"
app:menu="#menu/menu_navigation_drawer_top"
/>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_drawer_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/menuColor"
android:layout_gravity="bottom"
android:paddingLeft="50dp"
app:itemTextAppearance="#style/NavigationDrawerStyle"
app:itemTextColor="#color/menuTextColour"
app:menu="#menu/menu_navigation_drawer_bottom" />
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
try this
<View
android:layout_below="#+id/id_of_item_below_which_you_want_it"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"/>
It's quite simple to do. All you need to do is make a group and put unique id to the groups. The unique id is what plays the real trick in adding a divider to your menu.
Here is a quick example for you,
<group android:id="#+id/group1" android:checkableBehavior="single" >
<item
android:id="#+id/item_1"
android:checked="true"
android:icon="#drawable/ic_1"
android:title="#string/title_1" />
</group>
<group android:id="#+id/group2" android:checkableBehavior="single" >
<item
android:id="#+id/item_2"
android:icon="#drawable/ic_2"
android:title="#string/title_2" />
</group>
This will surely add dividers to your menus.
EDIT
As you are adding menus programmatically, you should try to get access to each NavigationMenuView and add a decorator to them.
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
NavigationMenuView navMenuView = (NavigationMenuView) navigationView.getChildAt(0);
navMenuView.addItemDecoration(new DividerItemDecoration(appContext,DividerItemDecoration.VERTICAL_LIST))
And here is the DividerItemDecoration class for you,
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
#Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
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 top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
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 left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
#Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
I have used the code from this answer to create a solid separator line for my RecyclerViews.
However, I would like the line to be dashed/dotted.
I already have a line_dashed.xml resource that I am using elsewhere in my app:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line" >
<stroke
android:color="#color/blue"
android:dashGap="12dp"
android:dashWidth="12dp"
android:width="1dp" />
</shape>
But if I try applying this as the drawable resource that is accessed via my call to recyclerView.addItemDecoration(new SimpleDividerItemDecoration(getContext())), no line is drawn at all.
How to solve so a dashed line is shown?
Just add your drawable resource into this item decorator.
DividerItemDecoration decorator = new DividerItemDecoration(ContextCompat.getDrawable(getContext(), R.drawable.line_dashed));
recyclerView.addItemDecoration(decorator);
and DividerItemDecorator class:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
private int mPaddingLeft;
public DividerItemDecoration(Drawable divider) {
mDivider = divider;
mPaddingLeft = 0;
}
public DividerItemDecoration(Drawable divider, int paddingLeft) {
mDivider = divider;
mPaddingLeft = paddingLeft;
}
#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.getChildAdapterPosition(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;
}
if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
final int left = parent.getPaddingLeft() + mPaddingLeft;
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int size = mDivider.getIntrinsicHeight();
final int top = child.getTop() - params.topMargin;
final int bottom = top + size;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} else { //horizontal
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int size = mDivider.getIntrinsicWidth();
final int left = child.getLeft() - params.leftMargin;
final int 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.");
}
}
Should work I tested it.
UPDATE:
android:layerType="software"
add this parameter in xml for recyclerView
Also add size into your shape drawable:
<size android:height="1dp"/>
currently u can use DividerItemDecoration from the box.
recyclerView.apply {
layoutManager = LinearLayoutManager(this#YourFragment.context)
adapter = this#YourFragment.adapter
addItemDecoration(
DividerItemDecoration(
this#YourFragment.context,
DividerItemDecoration.VERTICAL
).apply {
context.getDrawable(R.drawable.divider)?.let {
setDrawable(it)
}
}
)
}
Use the next shape XML:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<size android:height="1dp" />
<solid android:color="#color/primary" />
<stroke
android:width="0.5dp"
android:color="#color/primary"
android:dashWidth="5dp"
android:dashGap="5dp" />
</shape>
Attention: The stroke width must be less than the height of the line. In another case, the line will be not drawn.
Draw dashed line in Android is not so easy deal. Drowable like you showed and even just draw dotted line on canwas (canvas.drawLine(..., paintWithDashEffect)) not always works (not for all devices). You may use android:layerType="software" or draw path. IMHO, the better solution is to not draw dotted line at all (draw just line). But if you really need dotted line, you can use #fearless answer or somethink like this:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Paint mPaint;
private int mDividerSize;
public DividerItemDecoration(int dividerSize) {
mDividerSize = dividerSize;
mPaint = new Paint();
mPaint.setColor(ContextCompat.getColor(context, R.color.colorAccent));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(dividerSize);
mPaint.setPathEffect(new DashPathEffect(new float[]{dashGap,dashWidth},0));
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.bottom = mDividerSize;
}
#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();
Path path = new Path();
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 + mDividerSize/2;
path.moveTo(left, top);
path.lineTo(right, top);
}
c.drawPath(path, mPaint);
}
}
Is there any way to removing divider after a footer in a Recyclerview.I am using item decoration to add divider to the adapter.I am adding footer in the adapter.divider is showing below the footer also.i want to remove it.
This is my code for Divider
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
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 top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
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 left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
#Override
public void getItemOffsets(Rect rect, View view, RecyclerView parent, RecyclerView.State state) {
if (Orientation == VERTICAL_LIST) {
rect.set(0, 0, 0, Divider.getIntrinsicHeight());
} else {
rect.set(0, 0, Divider.getIntrinsicWidth(), 0);
}}
You have to add a check on getItemOffsets() method:
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) {
// set the rect's size
}
}
You can find an example of this implementation on my RecyclerViewDivider library on Github
Or you can simply add it as a Gradle dependency and check the javadoc:
dependencies {
...
compile 'com.github.fondesa:recycler-view-divider:1.1.3'
}
And use:
RecyclerViewDivider.with(context)
.addTo(recyclerView)
.visibilityFactory(new VisibilityFactory() {
#Override
public boolean displayDividerForItem(int listSize, int position) {
return position != listSize - 1;
}
})
.build()
.attach()