大家都知道,想给RecycleView设置分割线可以重写RecyclerView.ItemDecoration
项目过程中,遇到一个需求:RecycleView顶部有一条灰色的间隔,我想到了给RecycleView设置分割线的方法,当然只给第一个Item设置,而且在上方。
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;
    /**
     * Custom divider will be used
     */
    public MyDividerItemDecoration(Context context, int resId) {
        mDivider = ContextCompat.getDrawable(context, resId);
    }
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, 
                               RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        //因为绘制了顶部分割线,因此需要将第一行的item下移相应的距离
        //这里要注意,判断该RecycleView是什么布局,如果是竖直方向上的线性布局(水平方向上的这里没有考虑)
        //,那么需要让第一个Item下移,移动的距离是分割线的高度,因为分割线会占据Item的空间
        //如果是网格布局,那么需要把第一行的所有Item都下移相应的高度
        if (layoutManager instanceof LinearLayoutManager) {
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.set(0, mDivider.getIntrinsicHeight(), 0, 0);
            }
        }
        if (layoutManager instanceof GridLayoutManager) {
            if (parent.getChildAdapterPosition(view) >= 0 && 
                parent.getChildAdapterPosition(view) < getSpanCount(parent)) {
                outRect.set(0, mDivider.getIntrinsicHeight(), 0, 0);
            }
        }
    }
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        //绘制分割线
        int left = 0;
        int right = parent.getWidth();
        View child = parent.getChildAt(0);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        //不可以直接设置top = 0;因为这样的话分隔线就不会跟着移动,因为top = 0,是绝对位置,
        //所以应该设置为子view的相对位置
        //这样才可以跟着滑动。
        //child的顶部坐标,减去设置的margin_top的值,再减去child为了给分割线腾出空间所下滑的高度,
        //这样分割线才会在顶部
        int top = child.getTop() - params.topMargin - mDivider.getIntrinsicHeight();
        int bottom;
        bottom = top + mDivider.getIntrinsicHeight();
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
    private int getSpanCount(RecyclerView parent) {
        // 列数
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        } else if (layoutManager instanceof LinearLayoutManager) {
            spanCount = layoutManager.getItemCount();
        }
        return spanCount;
    }
在onDrawOver方法中可以绘制分割线。
这里有一个需要注意的坑,调试了很久,最终才发现,难受。
在onDrawOver里面,一开始我设置top = 0;因为绘制在顶部嘛。结果出现了一个现象,顶部分割线一直停留在顶部,不会跟着移动。最后改为int top = child.getTop() - params.topMargin - mDivider.getIntrinsicHeight();才成功了。为什么呢?
因为直接写top = 0;这是绝对位置了,要让分割线也跟着滑动,需要用的是相对位置,相对于item的位置,这样才能够跟着item滑动。
调用:
recyclerView.addItemDecoration(new MyDividerItemDecoration(this, R.drawable.item_decoration));
item_decoration代码如下:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="10dp" />
    <solid android:color="@color/comic_gray_bg" />
</shape>
原文:https://www.cnblogs.com/tangZH/p/9489486.html