1.原理篇
分割线添加原理参照链接:https://www.jianshu.com/p/4eff036360da
在RecyclerView中,Google又为我们提供了什么样的方法去添加分隔线呢?通过查看官方文档,它,提供了:addItemDecoration(RecyclerView.ItemDecoration decor)这个方法了设置分隔线,那问题又来了,RecyclerView.ItemDecoration是什么东西呢?继续查:然后发现如下:它原来是一个类,里面封装了三个方法:
(1)void getItemOffsets ()(2)void onDraw ()(3)void onDrawOver ()
通过上面的三个方法,可以看出,这是要自己直接画上去,准确的说这几个方法是:添加Divider,主要是找到添加Divider的位置, 而Divider是在drawable文件中写好了的。 利用onDraw和onDrawOver都差不多,我们在创建自己的Decoration类继承RecyclerView.ItemDecoration的时候,我们只要重写getItemOffsets(),还有onDraw()和onDrawOver两者其中之一就可以了.
那getItemOffsets()方法有什么用呢?从字面意思就是Item要偏移, 由于我们在Item和Item之间加入了分隔线,线其实本质就是一个长方形,也是用户自定义的,既然线也有长宽高,就画横线来说,上面的Item加入了分隔线,那下面的Item就要往下平移,平移的量就是分隔线的高度.
2.实战篇
package com.picc.vmeng.module.coterie.atapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
/**
* author:zhangfeng on 2018/1/18.
* desc:
*/
public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private int mHorizontalDividerHight;
private int mVerticalDividerHight;
private Paint mColorPaint;
private Drawable mDivider;
int spanCount = 1;
private DividerGridItemDecoration(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
/**
* @param context
* @param horizontalDividerHight 水平分割线的宽度 px
* @param verticalDividerHight 竖直分割线的宽度 px
* @param dividerColor 分割线颜色
*/
public DividerGridItemDecoration(Context context, int horizontalDividerHight, int verticalDividerHight, int dividerColor) {
this(context);
mHorizontalDividerHight = horizontalDividerHight;
mVerticalDividerHight = verticalDividerHight;
mColorPaint = new Paint();
mColorPaint.setColor(dividerColor);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
//画水平和垂直分割线
drawHorizontalDivider(c, parent);
drawVerticalDivider(c, parent);
}
private int getSpanCount(RecyclerView parent) {
// 列数
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
public void drawVerticalDivider(Canvas c, RecyclerView parent) {
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.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
int left = 0;
int right = 0;
//左边第一列
if ((i % spanCount) == 0) {
//item左边分割线
left = child.getLeft();
right = left + mVerticalDividerHight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
if (mColorPaint != null) {
c.drawRect(left, top, right, bottom, mColorPaint);
}
//item右边分割线
left = child.getRight() + params.rightMargin - mVerticalDividerHight;
right = left + mVerticalDividerHight;
} else {
//非左边第一列
left = child.getRight() + params.rightMargin - mVerticalDividerHight;
right = left + mVerticalDividerHight;
}
//画分割线
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
if (mColorPaint != null) {
c.drawRect(left, top, right, bottom, mColorPaint);
}
}
}
public void drawHorizontalDivider(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - params.leftMargin - mVerticalDividerHight;
final int right = child.getRight() + params.rightMargin;
int top = 0;
int bottom = 0;
// 最上面一行
if ((i / spanCount) == 0) {
//当前item最上面的分割线
top = child.getTop();
//当前item下面的分割线
bottom = top + mHorizontalDividerHight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
if (mColorPaint != null) {
c.drawRect(left, top, right, bottom, mColorPaint);
}
top = child.getBottom() + params.bottomMargin;
bottom = top + mHorizontalDividerHight;
} else {
top = child.getBottom() + params.bottomMargin;
bottom = top + mHorizontalDividerHight;
}
//画分割线
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
if (mColorPaint != null) {
c.drawRect(left, top, right, bottom, mColorPaint);
}
}
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
// 如果是最后一列,则不需要绘制右边
if ((pos + 1) % spanCount == 0) {
return true;
}
} else if (layoutManager instanceof LinearLayoutManager) {
int orientation = ((LinearLayoutManager) layoutManager)
.getOrientation();
if (orientation == LinearLayoutManager.VERTICAL) {
//不需要绘制右边
return true;
} else {
childCount = childCount - childCount % spanCount;
// 如果是最后一列,则不需要绘制右边
if (pos >= childCount) {
return true;
}
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
// 如果是最后一列,则不需要绘制右边
if ((pos + 1) % spanCount == 0) {
return true;
}
} else {
childCount = childCount - childCount % spanCount;
// 如果是最后一列,则不需要绘制右边
if (pos >= childCount) {
return true;
}
}
}
return false;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount) {
return true;
}
} else if (layoutManager instanceof LinearLayoutManager) {
int orientation = ((LinearLayoutManager) layoutManager)
.getOrientation();
// LinearLayoutManager 且纵向滚动
if (orientation == LinearLayoutManager.VERTICAL) {
// 如果是最后一行,则不需要绘制底部
if (pos + 1 == childCount)
return true;
} else {
// LinearLayoutManager 且横向滚动
// 如果是最后一行,则不需要绘制底部
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else {
// StaggeredGridLayoutManager 且横向滚动
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0) {
return true;
}
}
}
return false;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
int itemPosition = parent.getChildLayoutPosition(view);
// 如果是最后一行,则不需要绘制底部
if (isLastRaw(parent, itemPosition, spanCount, childCount)) {
outRect.set(0, 0, mVerticalDividerHight, 0);
// 如果是最后一行的最后一列,则不需要绘制
if (isLastColum(parent, itemPosition, spanCount, childCount)) {
outRect.set(0, 0, 0, 0);
}
// 如果是最后一列的最后一行,则不需要绘制右边
} else if (isLastColum(parent, itemPosition, spanCount, childCount)) {
outRect.set(0, 0, 0, mHorizontalDividerHight);
// 如果是最后一行的最后一列,则不需要绘制
if (isLastRaw(parent, itemPosition, spanCount, childCount)) {
outRect.set(0, 0, 0, 0);
}
} else {
outRect.set(0, 0, mVerticalDividerHight, mHorizontalDividerHight);
}
}
}
3.调用方法
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new DividerGridItemDecoration(this,20,10, Color.parseColor("#f3f3f3")));
recyclerView.setAdapter(mAdapter);
到这里所有的工作就完成了