RecyclerView通用分割線
摘要:
使用方式
listContent.addItemDecoration(
Divider.builder().
color(getResources().getColor(R.color.bgDefaul...
使用方式
listContent.addItemDecoration( Divider.builder(). color(getResources().getColor(R.color.bgDefaultColor)) .height(3) .build() );
使用範圍
GridLayoutManager;LinearLayoutManager;StaggeredGridLayoutManager;
程式碼來源
來自網路,已忘記開源作者
原始碼貼上
/** * 描述: 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;// 頭的數量 private int footerCount = 0;// 尾的數量 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;// 跳過,不繪製 int currentPosition = parent.getChildAdapterPosition(view); int spanCount = getSpanCount(parent);// 水平個數,線性佈局為-1 int childCount = parent.getAdapter().getItemCount();// 總個數 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當前的view,StaggeredGridLayoutManager 用 * @param parentRecyclerView * @param currentPosition 當前的位置,GridLayoutManager、LinearLayoutManager用 * @param spanCount列數 * @param adapterCountadapter的總數 * @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();// 去掉頭的數量 adapterCount -= getHeaderCount() + getFooterCount();// 去掉頭、尾的數量 // 判斷最後一個是否繪製 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 // 判斷最後一個是否繪製,垂直,不繪製右邊,直接返回true,水平,判斷,是否是最後一個 return ((LinearLayoutManager) layoutManager).getOrientation() == LinearLayout.VERTICAL || currentPosition == adapterCount - getFooterCount() - 1; } else if (layoutManager instanceof StaggeredGridLayoutManager) { // 判斷最後一個是否繪製,垂直,判斷是否是最後一列,是返回true,水平,都顯示,返回false StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); return ((StaggeredGridLayoutManager) layoutManager).getOrientation() == StaggeredGridLayoutManager.VERTICAL && (lp.getSpanIndex() + 1) % spanCount == 0; } return false; } /** * 是否不繪製底部 * * @param view當前的view,StaggeredGridLayoutManager 用 * @param parentRecyclerView * @param currentPosition 當前的位置,GridLayoutManager、LinearLayoutManager用 * @param spanCount列數 * @param adapterCountadapter的總數 * @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();// 去掉頭的數量 adapterCount -= getHeaderCount() + getFooterCount();// 去掉頭、尾的數量 // 判斷最後一個是否繪製 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 // 判斷最後一個是否繪製,垂直,判斷是否是最後一行,水平,直接返回true,不繪製底部 return ((LinearLayoutManager) layoutManager).getOrientation() != LinearLayout.VERTICAL || currentPosition == adapterCount - getFooterCount() - 1; } else if (layoutManager instanceof StaggeredGridLayoutManager) { // StaggeredGridLayoutManager // 判斷最後一個是否繪製,垂直,都顯示,返回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 parentRecyclerView * @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);// 水平個數,線性佈局為-1 int childCount = parent.getChildCount();// 顯示的個數 int adapterCount = parent.getAdapter().getItemCount();// 總個數 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)) // 跳過,直接返回 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;// 不繪製右部,公共區域不繪製 // 繪製下線 final int downLeft = child.getLeft() - params.leftMargin; final int downTop = child.getBottom() + params.bottomMargin; final int downRight = child.getRight() + params.rightMargin + bottomLineWidth;// 公共區域繪製 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;// 公共區域繪製 final int upBottom = upTop + lineHeight; dividerDrawable.setBounds(upLeft, upTop, upRight, upBottom); dividerDrawable.draw(canvas); } } canvas.restore(); } /** * 繪製垂直線 * * @param canvas畫布 * @param parentRecyclerView * @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);// 水平個數,線性佈局為-1 int childCount = parent.getChildCount(); int adapterCount = parent.getAdapter().getItemCount();// 總個數 for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); int currentPosition = parent.getChildAdapterPosition(child); if (isSkipDraw(parent, child)) // 跳過、不繪製右部,直接返回 continue; final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (!isNotDrawRight(child, parent, currentPosition, spanCount, adapterCount)) { // 不繪製右邊 if (isNotDrawBottom(child, parent, currentPosition, spanCount, adapterCount)) // 不繪製底部,公共區域不繪製 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;// 公共區域水平繪製 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;// 公共區域水平繪製 dividerDrawable.setBounds(left, top, right, bottom); dividerDrawable.draw(canvas); } } canvas.restore(); } /** * 是否是StaggeredGridLayoutManager的中間的view * * @param view測定的view * @param spanCount 列數 */ private boolean isStaggeredGridNotFirstView(View view, int spanCount) { StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); return lp.getSpanIndex() != 0; } /** * 是否跳過繪畫 * * @param parent RecyclerView * @param view當前View */ private boolean isSkipDraw(RecyclerView parent, View view) { int currentPosition = parent.getChildAdapterPosition(view);// 當前item總位置 int adapterCount = parent.getAdapter().getItemCount(); return currentPosition < getHeaderCount() || currentPosition >= adapterCount - getFooterCount(); } /** * 獲取列數 * * @param parent RecyclerView * @return 列數 */ 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 LinearLayoutManager) { spanCount = 1; } else if (layoutManager instanceof StaggeredGridLayoutManager) { spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount(); } return spanCount; } /** * 獲取線寬 */ public int getLineWidth() { return lineWidth; } /** * 設定線寬 */ public void setLineWidth(int lineWidth) { this.lineWidth = lineWidth; } /** * 獲取線高 */ public int getLineHeight() { return lineHeight; } /** * 設定線高 */ public void setLineHeight(int lineHeight) { this.lineHeight = lineHeight; } /** * 獲取線Drawable */ public Drawable getDividerDrawable() { return dividerDrawable; } /** * 設定線Drawable,和setLineColor()二選一 */ public void setDividerDrawable(Drawable dividerDrawable) { this.dividerDrawable = dividerDrawable; } /** * 設定線顏色,和setDividerDrawable()二選一 */ public void setLineColor(int lineColor) { this.dividerDrawable = new ColorDrawable(lineColor); } /** * 獲取頭數量 */ private int getHeaderCount() { return headerCount; } /** * 設定頭數量,即頭部跳過繪製 */ public void setHeaderCount(int headerCount) { this.headerCount = headerCount; } /** * 獲取尾數量 */ private int getFooterCount() { return footerCount; } /** * 設定尾數量,即尾部跳過繪製 */ public void setFooterCount(int footerCount) { this.footerCount = footerCount; } /** * Divider的構建者 */ public static Builder builder() { return new Builder(); } public static class Builder { private final Divider divider; Builder() { divider = new Divider(); } /** * 設定線寬 */ public Builder width(int lineWidth) { divider.setLineWidth(lineWidth); return this; } /** * 設定線高 */ public Builder height(int lineHeight) { divider.setLineHeight(lineHeight); return this; } /** * 同時設定線寬、線高 */ public Builder widthAndHeight(int lineSize) { divider.setLineWidth(lineSize); divider.setLineHeight(lineSize); return this; } /** * 設定線顏色,和drawable二選一 */ public Builder color(int lineColor) { divider.setLineColor(lineColor); return this; } /** * 設定線背景,和color二選一 */ public Builder drawable(Drawable dividerDrawable) { divider.setDividerDrawable(dividerDrawable); return this; } /** * 設定頭的數量 */ public Builder headerCount(int headerCount) { divider.setHeaderCount(headerCount); return this; } /** * 設定尾的數量 */ public Builder footerCount(int footerCount) { divider.setFooterCount(footerCount); return this; } /** * 返回Divider */ public Divider build() { return this.divider; } } }