Recylerview網格佈局分割線的實現,列表四周也有分割線
阿新 • • 發佈:2018-12-16
關於RecylerView分割線的問題,當佈局形式為線性佈局LinearLayoutManager的時候, 官方提供了一個定義好的分割線類DividerItemDecoration,但是當佈局形式為網格佈局GridLayoutManager的時候,官方沒有提供分割線的相關類,需要自己去實現,網上大多網格佈局分割線的實現都是item中間有間隔,列表四周沒有分割的,所以我這裡定義一個item四周也有分割間隙的網格佈局分割線GridItemDivider。
程式碼比較簡單,主要思路是:我們要判斷itemview在recylerview中的四種位置;
1. item是第一個,那麼四周都有分割線
2. item是第一行,畫上、下、右三邊的分割線
3. item是第一列,畫左、右、下三邊的分割線
4.其他情況,畫右、下兩邊的分割線
以上四種情況依次用if和else if 去判斷,重寫RecyclerView.ItemDecoration的getItemOffsets,分別對以上四種情況進行對應的itemview的縮排。下面的完整程式碼:
public class GridItemDivider extends RecyclerView.ItemDecoration { private String TAG = getClass().getSimpleName(); private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable divider; public GridItemDivider(Context context) { final TypedArray a = context.obtainStyledAttributes(ATTRS); divider = a.getDrawable(0); a.recycle(); } public GridItemDivider(Drawable drawable) { divider = drawable; } public GridItemDivider(int height, int color) { GradientDrawable shapeDrawable = new GradientDrawable(); shapeDrawable.setColor(color); shapeDrawable.setShape(GradientDrawable.RECTANGLE); shapeDrawable.setSize(height, height); divider = shapeDrawable; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { drawHorizontal(c, parent); drawVertical(c, parent); } 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(); } return spanCount; } public void drawHorizontal(Canvas c, RecyclerView parent) { int childCount = parent.getChildCount(); //獲取可見item的數量 int spanCount = getSpanCount(parent); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getLeft() - params.leftMargin; final int right = child.getRight() + params.rightMargin + divider.getIntrinsicWidth(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); if (i < spanCount) { //畫第一行頂部的分割線 drawHorizontalForFirstRow(c, child); } } } private void drawHorizontalForFirstRow(Canvas c, View child) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int left = child.getLeft() - params.leftMargin - divider.getIntrinsicWidth(); int top = child.getTop() - params.topMargin - divider.getIntrinsicHeight(); int right = child.getRight() + params.rightMargin + divider.getIntrinsicWidth(); int bottom = top + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); } private void drawVerticalForFirstColum(Canvas c, View child) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int left = child.getLeft() - params.leftMargin - divider.getIntrinsicWidth(); int top = child.getTop() - params.topMargin; int right = child.getLeft() - params.leftMargin; int bottom = top + child.getHeight() + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); } public void drawVertical(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; final int left = child.getRight() + params.rightMargin; final int right = left + divider.getIntrinsicWidth(); divider.setBounds(left, top, right, bottom); divider.draw(c); if (isFirstColum(parent, i, getSpanCount(parent))) { //畫第一列左邊分割線 drawVerticalForFirstColum(c, child); } } } 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 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 StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL) { childCount = childCount - childCount % spanCount; // 如果是最後一行,則不需要繪製底部 if (pos >= childCount) return true; } else { // 如果是最後一行,則不需要繪製底部 if ((pos + 1) % spanCount == 0) { return true; } } } return false; } //是否為第一列 private boolean isFirstColum(RecyclerView parent, int pos, int spanCount) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { //網格佈局 if ((pos + 1) % spanCount == 1) { return true; } } return false; } //是否為第一行 private boolean isFirstRaw(int pos, int spanCount) { if (pos < spanCount) { return true; } return false; } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { int spanCount = getSpanCount(parent); //列數 if (itemPosition == 0) { //第一行第一個,四邊都畫 outRect.set(divider.getIntrinsicWidth(), divider.getIntrinsicHeight(), divider.getIntrinsicWidth(), divider.getIntrinsicHeight()); } else if (isFirstRaw(itemPosition, spanCount)) { //第一行,畫上下右三邊 outRect.set(0, divider.getIntrinsicHeight(), divider.getIntrinsicWidth(), divider.getIntrinsicHeight()); } else if (isFirstColum(parent, itemPosition, spanCount)) { //第一列,畫左右下三邊 outRect.set(divider.getIntrinsicWidth(), 0, divider.getIntrinsicWidth(), divider.getIntrinsicHeight()); } else { //其他,畫右下兩邊 outRect.set(0, 0, divider.getIntrinsicWidth(), divider.getIntrinsicHeight()); } } }
程式碼比較簡單明瞭, 我就不詳細多說了,感謝大家支援!!