Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - How to add a dashed/dotted separator line for RecyclerView?

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?

like image 799
ban-geoengineering Avatar asked Sep 23 '16 18:09

ban-geoengineering


2 Answers

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"/>
like image 66
Mykhailo Avatar answered Oct 12 '22 21:10

Mykhailo


currently u can use DividerItemDecoration from the box.

recyclerView.apply {
        layoutManager = LinearLayoutManager([email protected])
        adapter = [email protected]
        addItemDecoration(
            DividerItemDecoration(
                [email protected],
                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.

like image 32
Alex Avatar answered Oct 12 '22 20:10

Alex