使用方式
listContent.addItemDecoration(
Divider.builder().
color(getResources().getColor(R.color.bgDefaultColor))
.height(3)
.build()
);
使用范圍
GridLayoutManager;
LinearLayoutManager;
StaggeredGridLayoutManager;
代碼來(lái)源
來(lái)自網(wǎng)絡(luò),已忘記開源作者
源碼粘貼
/**
* 描述: RecyclerView通用分割線
* @author Smile
*/
@SuppressWarnings("unused")
public class Divider extends RecyclerView.ItemDecoration {
private Drawable dividerDrawable;
private final int DEFAULT_LINE_WIDTH = 10;
private final int DEFAULT_LINE_HEIGHT = 20;
private int lineWidth = DEFAULT_LINE_WIDTH;// 線的寬度
private int lineHeight = DEFAULT_LINE_HEIGHT;// 線的高度
private int headerCount = 0;// 頭的數(shù)量
private int footerCount = 0;// 尾的數(shù)量
Divider() {
dividerDrawable = new ColorDrawable(Color.GRAY);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (isSkipDraw(parent, view))
return;// 跳過(guò)账嚎,不繪制
int currentPosition = parent.getChildAdapterPosition(view);
int spanCount = getSpanCount(parent);// 水平個(gè)數(shù),線性布局為-1
int childCount = parent.getAdapter().getItemCount();// 總個(gè)數(shù)
int right = lineWidth;
int bottom = lineHeight;
if (isNotDrawBottom(view, parent, currentPosition, spanCount, childCount))
// 如果是最后一行机错,則不需要繪制底部
bottom = 0;
if (isNotDrawRight(view, parent, currentPosition, spanCount, childCount))
// 如果是最后一列,則不需要繪制右邊
right = 0;
outRect.set(0, 0, right, bottom);
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
drawHorizontal(canvas, parent, lineWidth, lineHeight);
drawVertical(canvas, parent, lineWidth, lineHeight);
}
/**
* 是否不繪制右部
*
* @param view 當(dāng)前的view,StaggeredGridLayoutManager 用
* @param parent RecyclerView
* @param currentPosition 當(dāng)前的位置乡摹,GridLayoutManager、LinearLayoutManager用
* @param spanCount 列數(shù)
* @param adapterCount adapter的總數(shù)
* @return 返回true代表不繪制右部采转,返回false聪廉,代表繪制右部
*/
private boolean isNotDrawRight(View view, RecyclerView parent, int currentPosition, int spanCount, int adapterCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
// GridLayoutManager
currentPosition -= getHeaderCount();// 去掉頭的數(shù)量
adapterCount -= getHeaderCount() + getFooterCount();// 去掉頭、尾的數(shù)量
// 判斷最后一個(gè)是否繪制
if (((GridLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.VERTICAL) {
// 垂直故慈,判斷是否是最后一列
return (currentPosition + 1) % spanCount == 0;
} else {
// 水平板熊,判斷是不是最后的
if (adapterCount % spanCount == 0)
return currentPosition >= adapterCount - spanCount;
else
return currentPosition >= adapterCount - adapterCount % spanCount;
}
} else if (layoutManager instanceof LinearLayoutManager) {
// LinearLayoutManager
// 判斷最后一個(gè)是否繪制,垂直察绷,不繪制右邊干签,直接返回true,水平,判斷拆撼,是否是最后一個(gè)
return ((LinearLayoutManager) layoutManager).getOrientation() == LinearLayout.VERTICAL || currentPosition == adapterCount - getFooterCount() - 1;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
// 判斷最后一個(gè)是否繪制容劳,垂直,判斷是否是最后一列闸度,是返回true竭贩,水平句惯,都顯示雨膨,返回false
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
return ((StaggeredGridLayoutManager) layoutManager).getOrientation() == StaggeredGridLayoutManager.VERTICAL && (lp.getSpanIndex() + 1) % spanCount == 0;
}
return false;
}
/**
* 是否不繪制底部
*
* @param view 當(dāng)前的view,StaggeredGridLayoutManager 用
* @param parent RecyclerView
* @param currentPosition 當(dāng)前的位置赡勘,GridLayoutManager哟冬、LinearLayoutManager用
* @param spanCount 列數(shù)
* @param adapterCount adapter的總數(shù)
* @return 返回true代表不繪制底部楼熄,返回false,代表繪制底部
*/
private boolean isNotDrawBottom(View view, RecyclerView parent, int currentPosition, int spanCount, int adapterCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
// GridLayoutManager
currentPosition -= getHeaderCount();// 去掉頭的數(shù)量
adapterCount -= getHeaderCount() + getFooterCount();// 去掉頭柒傻、尾的數(shù)量
// 判斷最后一個(gè)是否繪制
if (((GridLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.VERTICAL) {
// 垂直孝赫,判斷是不是最后的
if (adapterCount % spanCount == 0)
return currentPosition >= adapterCount - spanCount;
else
return currentPosition >= adapterCount - adapterCount % spanCount;
} else {
// 水平,判斷是不是最后一列
return (currentPosition + 1) % spanCount == 0;
}
} else if (layoutManager instanceof LinearLayoutManager) {
// LinearLayoutManager
// 判斷最后一個(gè)是否繪制红符,垂直青柄,判斷是否是最后一行,水平,直接返回true预侯,不繪制底部
return ((LinearLayoutManager) layoutManager).getOrientation() != LinearLayout.VERTICAL || currentPosition == adapterCount - getFooterCount() - 1;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
// StaggeredGridLayoutManager
// 判斷最后一個(gè)是否繪制致开,垂直,都顯示萎馅,返回false双戳, 水平,判斷是否是最后一列糜芳,是返回true
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
return ((StaggeredGridLayoutManager) layoutManager).getOrientation() != StaggeredGridLayoutManager.VERTICAL && (lp.getSpanIndex() + 1) % spanCount == 0;
}
return false;
}
/**
* 繪制水平線
*
* @param canvas 畫布
* @param parent RecyclerView
* @param lineWidth 線寬
* @param lineHeight 線高
*/
private void drawHorizontal(Canvas canvas, RecyclerView parent, int lineWidth, int lineHeight) {
boolean isDrawDoubleLine = false;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof StaggeredGridLayoutManager && ((StaggeredGridLayoutManager) layoutManager).getOrientation() == StaggeredGridLayoutManager.HORIZONTAL)
// 繪制雙線
isDrawDoubleLine = true;
canvas.save();
int spanCount = getSpanCount(parent);// 水平個(gè)數(shù)飒货,線性布局為-1
int childCount = parent.getChildCount();// 顯示的個(gè)數(shù)
int adapterCount = parent.getAdapter().getItemCount();// 總個(gè)數(shù)
if (parent.getClipToPadding()) {
canvas.clipRect(parent.getPaddingLeft(), parent.getPaddingTop(),
parent.getWidth() - parent.getPaddingRight(),
parent.getHeight() - parent.getPaddingBottom());
}
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
int currentPosition = parent.getChildAdapterPosition(child);
if (isSkipDraw(parent, child))
// 跳過(guò)魄衅,直接返回
continue;
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
if (!isNotDrawBottom(child, parent, currentPosition, spanCount, adapterCount)) {
// 繪制底部
int bottomLineWidth = isNotDrawRight(child, parent, currentPosition, spanCount, adapterCount) ? 0 : lineWidth;// 不繪制右部,公共區(qū)域不繪制
// 繪制下線
final int downLeft = child.getLeft() - params.leftMargin;
final int downTop = child.getBottom() + params.bottomMargin;
final int downRight = child.getRight() + params.rightMargin + bottomLineWidth;// 公共區(qū)域繪制
final int downBottom = downTop + lineHeight;
dividerDrawable.setBounds(downLeft, downTop, downRight, downBottom);
dividerDrawable.draw(canvas);
}
// 判斷是否繪制雙線
if (isDrawDoubleLine && isStaggeredGridNotFirstView(child, spanCount)) {
// 繪制上線
final int upLeft = child.getLeft() - params.leftMargin;
final int upTop = child.getTop() + params.topMargin - lineHeight;
final int upRight = child.getRight() + params.rightMargin + lineWidth;// 公共區(qū)域繪制
final int upBottom = upTop + lineHeight;
dividerDrawable.setBounds(upLeft, upTop, upRight, upBottom);
dividerDrawable.draw(canvas);
}
}
canvas.restore();
}
/**
* 繪制垂直線
*
* @param canvas 畫布
* @param parent RecyclerView
* @param lineWidth 線寬
* @param lineHeight 線高
*/
private void drawVertical(Canvas canvas, RecyclerView parent, int lineWidth, int lineHeight) {
boolean isDrawDoubleLine = false;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof StaggeredGridLayoutManager && ((StaggeredGridLayoutManager) layoutManager).getOrientation() == StaggeredGridLayoutManager.VERTICAL)
// 繪制雙線
isDrawDoubleLine = true;
canvas.save();
if (parent.getClipToPadding()) {
canvas.clipRect(parent.getPaddingLeft(), parent.getPaddingTop(),
parent.getWidth() - parent.getPaddingRight(),
parent.getHeight() - parent.getPaddingBottom());
}
int spanCount = getSpanCount(parent);// 水平個(gè)數(shù)塘辅,線性布局為-1
int childCount = parent.getChildCount();
int adapterCount = parent.getAdapter().getItemCount();// 總個(gè)數(shù)
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
int currentPosition = parent.getChildAdapterPosition(child);
if (isSkipDraw(parent, child))
// 跳過(guò)晃虫、不繪制右部,直接返回
continue;
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
if (!isNotDrawRight(child, parent, currentPosition, spanCount, adapterCount)) {
// 不繪制右邊
if (isNotDrawBottom(child, parent, currentPosition, spanCount, adapterCount))
// 不繪制底部扣墩,公共區(qū)域不繪制
lineHeight = 0;
final int left = child.getRight() + params.rightMargin;
final int top = child.getTop() - params.topMargin;
final int right = left + lineWidth;
final int bottom = child.getBottom() + params.bottomMargin + lineHeight;// 公共區(qū)域水平繪制
dividerDrawable.setBounds(left, top, right, bottom);
dividerDrawable.draw(canvas);
}
// 判斷是否繪制雙線
if (isDrawDoubleLine && isStaggeredGridNotFirstView(child, spanCount)) {
// 繪制左線
final int left = child.getLeft() + params.leftMargin - lineWidth;
final int top = child.getTop() - params.topMargin;
final int right = left + lineWidth;
final int bottom = child.getBottom() + params.bottomMargin + lineHeight;// 公共區(qū)域水平繪制
dividerDrawable.setBounds(left, top, right, bottom);
dividerDrawable.draw(canvas);
}
}
canvas.restore();
}
/**
* 是否是StaggeredGridLayoutManager的中間的view
*
* @param view 測(cè)定的view
* @param spanCount 列數(shù)
*/
private boolean isStaggeredGridNotFirstView(View view, int spanCount) {
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
return lp.getSpanIndex() != 0;
}
/**
* 是否跳過(guò)繪畫
*
* @param parent RecyclerView
* @param view 當(dāng)前View
*/
private boolean isSkipDraw(RecyclerView parent, View view) {
int currentPosition = parent.getChildAdapterPosition(view);// 當(dāng)前item總位置
int adapterCount = parent.getAdapter().getItemCount();
return currentPosition < getHeaderCount() || currentPosition >= adapterCount - getFooterCount();
}
/**
* 獲取列數(shù)
*
* @param parent RecyclerView
* @return 列數(shù)
*/
private int getSpanCount(RecyclerView parent) {
// 列數(shù)
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof LinearLayoutManager) {
spanCount = 1;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
return spanCount;
}
/**
* 獲取線寬
*/
public int getLineWidth() {
return lineWidth;
}
/**
* 設(shè)置線寬
*/
public void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
}
/**
* 獲取線高
*/
public int getLineHeight() {
return lineHeight;
}
/**
* 設(shè)置線高
*/
public void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
}
/**
* 獲取線Drawable
*/
public Drawable getDividerDrawable() {
return dividerDrawable;
}
/**
* 設(shè)置線Drawable哲银,和setLineColor()二選一
*/
public void setDividerDrawable(Drawable dividerDrawable) {
this.dividerDrawable = dividerDrawable;
}
/**
* 設(shè)置線顏色,和setDividerDrawable()二選一
*/
public void setLineColor(int lineColor) {
this.dividerDrawable = new ColorDrawable(lineColor);
}
/**
* 獲取頭數(shù)量
*/
private int getHeaderCount() {
return headerCount;
}
/**
* 設(shè)置頭數(shù)量呻惕,即頭部跳過(guò)繪制
*/
public void setHeaderCount(int headerCount) {
this.headerCount = headerCount;
}
/**
* 獲取尾數(shù)量
*/
private int getFooterCount() {
return footerCount;
}
/**
* 設(shè)置尾數(shù)量荆责,即尾部跳過(guò)繪制
*/
public void setFooterCount(int footerCount) {
this.footerCount = footerCount;
}
/**
* Divider的構(gòu)建者
*/
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final Divider divider;
Builder() {
divider = new Divider();
}
/**
* 設(shè)置線寬
*/
public Builder width(int lineWidth) {
divider.setLineWidth(lineWidth);
return this;
}
/**
* 設(shè)置線高
*/
public Builder height(int lineHeight) {
divider.setLineHeight(lineHeight);
return this;
}
/**
* 同時(shí)設(shè)置線寬、線高
*/
public Builder widthAndHeight(int lineSize) {
divider.setLineWidth(lineSize);
divider.setLineHeight(lineSize);
return this;
}
/**
* 設(shè)置線顏色亚脆,和drawable二選一
*/
public Builder color(int lineColor) {
divider.setLineColor(lineColor);
return this;
}
/**
* 設(shè)置線背景做院,和color二選一
*/
public Builder drawable(Drawable dividerDrawable) {
divider.setDividerDrawable(dividerDrawable);
return this;
}
/**
* 設(shè)置頭的數(shù)量
*/
public Builder headerCount(int headerCount) {
divider.setHeaderCount(headerCount);
return this;
}
/**
* 設(shè)置尾的數(shù)量
*/
public Builder footerCount(int footerCount) {
divider.setFooterCount(footerCount);
return this;
}
/**
* 返回Divider
*/
public Divider build() {
return this.divider;
}
}
}