前言:
现在的RecyclerView几乎已经完全取代ListView和GridView了,已经几年没使用ListView和GridView了,想当年还需要自己在getView方法中复用convertView。而现在的RecyclerView一出生就被设计成convertView复用的,尽管你不想复用(才怪)。RecyclerView功能如此强大的同时就会面临许多需求,如给RecyclerView的item添加分割线,给RecyclerView添加下拉刷新,上拉加载更多的功能等等。这篇文章就将为RecyclerView添加中间分割线做个简单的介绍,其实给RecyclerView添加分割线并没有你想象的那么难,只要你肯动手,你就会拥有属于你自己的分割线,想怎么画就怎么画。
实现效果图:
为RecyclerView添加分割线需通过RecyclerView的addItemDecoration方法,addItemDecoration方法需接受一个ItemDecoration类型的对象。为此,我们首先需要自定义一个类继承于ItemDecoration并实现getItemOffsets和SpaceItemDecoration两个方法,步骤如下。
- 重写getItemOffsets方法,给每个Item设置合适的偏移量(left,top,right,bottom);
- 重写onDraw方法,给每个item绘制分隔线(矩形)。
1. 重写getItemOffsets
这个方法在RecyclerView渲染item的时候通过getItemOffsets方法的Rect类型的参数outRect的left,top,right,bottom四个属性为item设置相应的偏移量,如:
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// 获取位置
int position = parent.getChildAdapterPosition(view);
view.setTag(position);
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if(layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
mSpanCount = gridLayoutManager.getSpanCount();
mMaxSpanGroupIndex = spanSizeLookup.getSpanGroupIndex(parent.getAdapter().getItemCount() - 1, mSpanCount);
int spanSize = spanSizeLookup.getSpanSize(position);
int spanIndex = spanSizeLookup.getSpanIndex(position, mSpanCount);
int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, mSpanCount);
Log.d(TAG, "getItemOffsets: spanIndex:" + spanIndex);
if (spanSize <mSpanCount && spanIndex != 0) {
// 左边需要偏移
outRect.left = mSpace;
}
if(spanGroupIndex != 0) {
outRect.top = mSpace;
}
}else if(layoutManager instanceof LinearLayoutManager){
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
if(position != 0) {
if (linearLayoutManager.getOrientation() == LinearLayoutManager.HORIZONTAL) {
outRect.left = mSpace;
} else {
outRect.top = mSpace;
}
}
}
}
在上面getItemOffsets方法中首先通过RecyclerView的getChildAdapterPosition方法获得item在Adapter中的位置并设置给它的tag属性保存下来,然后判断布局管理器的类型。如果布局管理器是GridLayoutManager类型,那么就需要判断当前Item不是位于该行的第一个(spanIndex != 0)并且没有占据一行(spanSize < mSpanCount)的时候就需要给Item设置left偏移量为我们的Space,如果当Item所在的行不是第一行(spanGroupIndex != 0)的时候需要给Item设置top偏移。当布局管理器为LinearLayoutManager的时候那就更简单了,先判断当前Item的position是不是第一个,如果不是第一个那么再判断布局管理器是横向还是纵向的,如果是横向,那么设置Item的left偏移量为Space,反之设置Item的top偏移量为Space。