注:本文基于 Android RecyclerView 使用完全解析 体验艺术般的控件 中关于GridView网格分割线部分代码扩展而来。
原接口代码:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {private static final int[] ATTRS = new int[]{android.R.attr.listDivider};private Drawable mDivider;public DividerGridItemDecoration(Context context) {final TypedArray a = context.obtainStyledAttributes(ATTRS);mDivider = a.getDrawable(0);a.recycle();}@Overridepublic void onDraw(Canvas c, RecyclerView parent, State state) {drawHorizontal(c, parent);drawVertical(c, parent);}private int getSpanCount(RecyclerView parent) {// 列数int spanCount = -1;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();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 + mDivider.getIntrinsicWidth();final int top = child.getBottom() + params.bottomMargin;final int bottom = top + mDivider.getIntrinsicHeight();mDivider.setBounds(left, top, right, bottom);mDivider.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 + mDivider.getIntrinsicWidth();mDivider.setBounds(left, top, right, bottom);mDivider.draw(c);}}private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) {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) {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();// StaggeredGridLayoutManager 且纵向滚动if (orientation == StaggeredGridLayoutManager.VERTICAL) {childCount = childCount - childCount % spanCount;// 如果是最后一行,则不需要绘制底部if (pos >= childCount)return true;} else {// 如果是最后一行,则不需要绘制底部if ((pos + 1) % spanCount == 0) {return true;}}}return false;}@Overridepublic void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {int spanCount = getSpanCount(parent);int childCount = parent.getAdapter().getItemCount();// 如果是最后一行,则不需要绘制底部if (isLastRaw(parent, itemPosition, spanCount, childCount)) {outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);} else if (isLastColum(parent, itemPosition, spanCount, childCount)) {// 如果是最后一列,则不需要绘制右边outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());} else {outRect.set(0, 0, mDivider.getIntrinsicWidth(),mDivider.getIntrinsicHeight());}}
}
扩展后的代码:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {private static final int[] ATTRS = new int[]{android.R.attr.listDivider};private Drawable mDivider;private Paint mColorPaint;private int mDividerHeight = 1;public DividerGridItemDecoration(Context context) {final TypedArray a = context.obtainStyledAttributes(ATTRS);mDivider = a.getDrawable(0);a.recycle();}public DividerGridItemDecoration(Context context, int color, int height) {this(context);mColorPaint = new Paint();mColorPaint.setColor(color);mDividerHeight = height;}@Overridepublic void onDraw(Canvas c, RecyclerView parent, State state) {drawHorizontal(c, parent);drawVertical(c, parent);}private int getSpanCount(RecyclerView parent) {// 列数int spanCount = -1;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();int spanCount = getSpanCount(parent);int count = 0;if (childCount % spanCount != 0) {count = childCount;} else {count = childCount - spanCount;}for (int i = 0; i < count; 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 + mDivider.getIntrinsicWidth();final int top = child.getBottom() + params.bottomMargin;final int bottom = top + mDivider.getIntrinsicHeight();if (mColorPaint != null) {c.drawRect(left, top, right, top + mDividerHeight, mColorPaint);} else {mDivider.setBounds(left, top, right, bottom);mDivider.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 + mDivider.getIntrinsicWidth();if (mColorPaint != null) {c.drawRect(left, top, left + mDividerHeight, bottom, mColorPaint);} else {mDivider.setBounds(left, top, right, bottom);mDivider.draw(c);}}}private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) {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) {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();// StaggeredGridLayoutManager 且纵向滚动if (orientation == StaggeredGridLayoutManager.VERTICAL) {childCount = childCount - childCount % spanCount;// 如果是最后一行,则不需要绘制底部if (pos >= childCount)return true;} else {// 如果是最后一行,则不需要绘制底部if ((pos + 1) % spanCount == 0) {return true;}}}return false;}@Overridepublic void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {int spanCount = getSpanCount(parent);int childCount = parent.getAdapter().getItemCount();// 如果是最后一行,则不需要绘制底部if (isLastRaw(parent, itemPosition, spanCount, childCount)) {outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);} else if (isLastColum(parent, itemPosition, spanCount, childCount)) {// 如果是最后一列,则不需要绘制右边outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());} else {outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());}}
}
扩展的内容:
- 最后一行不画分割线。通常我们的需求是边框都不进行分割的绘制,而原来的代码没有做这部分的处理。(原接口只处理了最后一列的情况)
- 支持分割线的颜色和宽度绘制的定制化。(原接口只支持系统属性分割线的绘制)。绘制方式:DividerGridItemDecoration(Context context, int color, int height) 通过传递color和height进行绘制定制化。