RecyclerView万能分割线

RecyclerView万能分割线_第1张图片

效果

实现思路

  • 核心方法
    绘制分割线的核心方法onDraw();
    定位分割线位置(也可以说是与其他组件之间的空隙)方法getItemOffsets()

  • 计算
    每条分割线的长度都是根据每一个ItemVIew的长度计算,位置同样根据ItemView的位置来确定,详细的计算在drawTop()drawLeft()drawRight()drawBottom()、四个方法中!

灵魂图解

RecyclerView万能分割线_第2张图片

完整代码

/**
 * 万能分割线
 * 

* 横向列表分割线 {@link #HORIZONTAL_DIV} * 纵向列表分割线 {@link #VERTICAL_DIV} * 表格列表分割线 {@link #GRID_DIV} *

*/ public class ItemDecorationPowerful extends RecyclerView.ItemDecoration { private static final String TAG = "ItemDecorationPowerful"; //横向布局分割线 public static final int HORIZONTAL_DIV = 0; //纵向布局分割线 public static final int VERTICAL_DIV = 1; //表格布局分割线 public static final int GRID_DIV = 2; private int mOrientation; private int mDividerWidth = 0; private Paint mPaint; /** * 默认纵向布分割线 */ public ItemDecorationPowerful() { this(VERTICAL_DIV); } /** * @param orientation 方向类型 */ public ItemDecorationPowerful(int orientation) { this(orientation, Color.parseColor("#808080"), 2); } /** * @param orientation 方向类型 * @param color 分割线颜色 * @param divWidth 分割线宽度 */ public ItemDecorationPowerful(int orientation, int color, int divWidth) { this.setOrientation(orientation); mDividerWidth = divWidth; mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(color); mPaint.setStyle(Paint.Style.FILL); } @Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { switch (mOrientation) { case HORIZONTAL_DIV: //横向布局分割线 drawHorizontal(c, parent); break; case VERTICAL_DIV: //纵向布局分割线 drawVertical(c, parent); break; case GRID_DIV: //表格格局分割线 drawGrid(c, parent); break; default: //纵向布局分割线 drawVertical(c, parent); break; } } @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { int itemPosition = parent.getChildAdapterPosition(view); RecyclerView.Adapter mAdapter = parent.getAdapter(); if (mAdapter != null) { int mChildCount = mAdapter.getItemCount(); switch (mOrientation) { case HORIZONTAL_DIV: /** * 横向布局分割线 *

* 如果是第一个Item,则不需要分割线 *

*/ if (itemPosition != 0) { outRect.set(mDividerWidth, 0, 0, 0); } break; case VERTICAL_DIV: /** * 纵向布局分割线 *

* 如果是第一个Item,则不需要分割线 *

*/ if (itemPosition != 0) { outRect.set(0, mDividerWidth, 0, 0); } break; case GRID_DIV: /** * 表格格局分割线 *

* 1:当是第一个Item的时候,四周全部需要分割线 * 2:当是第一行Item的时候,需要额外添加顶部的分割线 * 3:当是第一列Item的时候,需要额外添加左侧的分割线 * 4:默认情况全部添加底部和右侧的分割线 *

*/ RecyclerView.LayoutManager mLayoutManager = parent.getLayoutManager(); if (mLayoutManager instanceof GridLayoutManager) { GridLayoutManager mGridLayoutManager = (GridLayoutManager) mLayoutManager; int mSpanCount = mGridLayoutManager.getSpanCount(); if (itemPosition == 0) {//1 outRect.set(mDividerWidth, mDividerWidth, mDividerWidth, mDividerWidth); } else if ((itemPosition + 1) <= mSpanCount) {//2 outRect.set(0, mDividerWidth, mDividerWidth, mDividerWidth); } else if (((itemPosition + mSpanCount) % mSpanCount) == 0) {//3 outRect.set(mDividerWidth, 0, mDividerWidth, mDividerWidth); } else {//4 outRect.set(0, 0, mDividerWidth, mDividerWidth); } } break; default: //纵向布局分割线 if (itemPosition != (mChildCount - 1)) { outRect.set(0, 0, 0, mDividerWidth); } break; } } } /** * 绘制横向列表分割线 * * @param c 绘制容器 * @param parent RecyclerView */ private void drawHorizontal(Canvas c, RecyclerView parent) { int mChildCount = parent.getChildCount(); for (int i = 0; i < mChildCount; i++) { View mChild = parent.getChildAt(i); drawLeft(c, mChild, parent); } } /** * 绘制纵向列表分割线 * * @param c 绘制容器 * @param parent RecyclerView */ private void drawVertical(Canvas c, RecyclerView parent) { int mChildCount = parent.getChildCount(); for (int i = 0; i < mChildCount; i++) { View mChild = parent.getChildAt(i); drawTop(c, mChild, parent); } } /** * 绘制表格类型分割线 * * @param c 绘制容器 * @param parent RecyclerView */ private void drawGrid(Canvas c, RecyclerView parent) { int mChildCount = parent.getChildCount(); for (int i = 0; i < mChildCount; i++) { View mChild = parent.getChildAt(i); RecyclerView.LayoutManager mLayoutManager = parent.getLayoutManager(); if (mLayoutManager instanceof GridLayoutManager) { GridLayoutManager mGridLayoutManager = (GridLayoutManager) mLayoutManager; int mSpanCount = mGridLayoutManager.getSpanCount(); if (i == 0) { drawTop(c, mChild, parent); drawLeft(c, mChild, parent); } if ((i + 1) <= mSpanCount) { drawTop(c, mChild, parent); } if (((i + mSpanCount) % mSpanCount) == 0) { drawLeft(c, mChild, parent); } drawRight(c, mChild, parent); drawBottom(c, mChild, parent); } } } /** * 绘制右边分割线 * * @param c 绘制容器 * @param mChild 对应ItemView * @param recyclerView RecyclerView */ private void drawLeft(Canvas c, View mChild, RecyclerView recyclerView) { RecyclerView.LayoutParams mChildLayoutParams = (RecyclerView.LayoutParams) mChild.getLayoutParams(); int left = mChild.getLeft() - mDividerWidth - mChildLayoutParams.leftMargin; int top = mChild.getTop() - mChildLayoutParams.topMargin; int right = mChild.getLeft() - mChildLayoutParams.leftMargin; int bottom; if (isGridLayoutManager(recyclerView)) { bottom = mChild.getBottom() + mChildLayoutParams.bottomMargin + mDividerWidth; } else { bottom = mChild.getBottom() + mChildLayoutParams.bottomMargin; } c.drawRect(left, top, right, bottom, mPaint); } /** * 绘制顶部分割线 * * @param c 绘制容器 * @param mChild 对应ItemView * @param recyclerView RecyclerView */ private void drawTop(Canvas c, View mChild, RecyclerView recyclerView) { RecyclerView.LayoutParams mChildLayoutParams = (RecyclerView.LayoutParams) mChild.getLayoutParams(); int left; int top = mChild.getTop() - mChildLayoutParams.topMargin - mDividerWidth; int right = mChild.getRight() + mChildLayoutParams.rightMargin; int bottom = mChild.getTop() - mChildLayoutParams.topMargin; if (isGridLayoutManager(recyclerView)) { left = mChild.getLeft() - mChildLayoutParams.leftMargin - mDividerWidth; } else { left = mChild.getLeft() - mChildLayoutParams.leftMargin; } c.drawRect(left, top, right, bottom, mPaint); } /** * 绘制右边分割线 * * @param c 绘制容器 * @param mChild 对应ItemView * @param recyclerView RecyclerView */ private void drawRight(Canvas c, View mChild, RecyclerView recyclerView) { RecyclerView.LayoutParams mChildLayoutParams = (RecyclerView.LayoutParams) mChild.getLayoutParams(); int left = mChild.getRight() + mChildLayoutParams.rightMargin; int top; int right = left + mDividerWidth; int bottom = mChild.getBottom() + mChildLayoutParams.bottomMargin; if (isGridLayoutManager(recyclerView)) { top = mChild.getTop() - mChildLayoutParams.topMargin - mDividerWidth; } else { top = mChild.getTop() - mChildLayoutParams.topMargin; } c.drawRect(left, top, right, bottom, mPaint); } /** * 绘制底部分割线 * * @param c 绘制容器 * @param mChild 对应ItemView * @param recyclerView RecyclerView */ private void drawBottom(Canvas c, View mChild, RecyclerView recyclerView) { RecyclerView.LayoutParams mChildLayoutParams = (RecyclerView.LayoutParams) mChild.getLayoutParams(); int left = mChild.getLeft() - mChildLayoutParams.leftMargin; int top = mChild.getBottom() + mChildLayoutParams.bottomMargin; int bottom = top + mDividerWidth; int right; if (isGridLayoutManager(recyclerView)) { right = mChild.getRight() + mChildLayoutParams.rightMargin + mDividerWidth; } else { right = mChild.getRight() + mChildLayoutParams.rightMargin; } c.drawRect(left, top, right, bottom, mPaint); } /** * 判断RecyclerView所加载LayoutManager是否为GridLayoutManager * * @param recyclerView RecyclerView * @return 是GridLayoutManager返回true,否则返回false */ private boolean isGridLayoutManager(RecyclerView recyclerView) { RecyclerView.LayoutManager mLayoutManager = recyclerView.getLayoutManager(); return (mLayoutManager instanceof GridLayoutManager); } /** * 初始化分割线类型 * * @param orientation 分割线类型 */ public void setOrientation(int orientation) { if (mOrientation != HORIZONTAL_DIV && mOrientation != VERTICAL_DIV && mOrientation != GRID_DIV) { throw new IllegalArgumentException("ItemDecorationPowerful:分割线类型设置异常"); } else { this.mOrientation = orientation; } } }

你可能感兴趣的:(Android杂货铺)