效果

实现思路

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

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

灵魂图解

完整代码

/*** 万能分割线* <p>* 横向列表分割线 {@link #HORIZONTAL_DIV}* 纵向列表分割线 {@link #VERTICAL_DIV}* 表格列表分割线 {@link #GRID_DIV}* </P>*/
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);}@Overridepublic 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;}}@Overridepublic 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:/*** 横向布局分割线* <p>*     如果是第一个Item,则不需要分割线* </p>*/if (itemPosition != 0) {outRect.set(mDividerWidth, 0, 0, 0);}break;case VERTICAL_DIV:/*** 纵向布局分割线* <p>*     如果是第一个Item,则不需要分割线* </p>*/if (itemPosition != 0) {outRect.set(0, mDividerWidth, 0, 0);}break;case GRID_DIV:/*** 表格格局分割线* <p>*      1:当是第一个Item的时候,四周全部需要分割线*      2:当是第一行Item的时候,需要额外添加顶部的分割线*      3:当是第一列Item的时候,需要额外添加左侧的分割线*      4:默认情况全部添加底部和右侧的分割线* </p>*/RecyclerView.LayoutManager mLayoutManager = parent.getLayoutManager();if (mLayoutManager instanceof GridLayoutManager) {GridLayoutManager mGridLayoutManager = (GridLayoutManager) mLayoutManager;int mSpanCount = mGridLayoutManager.getSpanCount();if (itemPosition == 0) {//1outRect.set(mDividerWidth, mDividerWidth, mDividerWidth, mDividerWidth);} else if ((itemPosition + 1) <= mSpanCount) {//2outRect.set(0, mDividerWidth, mDividerWidth, mDividerWidth);} else if (((itemPosition + mSpanCount) % mSpanCount) == 0) {//3outRect.set(mDividerWidth, 0, mDividerWidth, mDividerWidth);} else {//4outRect.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;}}
}

了解RecyclerView的分割线相关推荐

  1. 自定义RecyclerView.ItemDecoration,实现RecyclerView的分割线效果

    [转] 原文 自定义RecyclerView.ItemDecoration,实现RecyclerView的分割线效果 字数1598 阅读302 评论2 喜欢23 1.背景   RecyclerView ...

  2. RecyclerView 官方分割线

    DividerItemDecoration 官方的分割线 今天忽然看到一个好东西,给大家分享一下.在API 25之后,Google添加了一个DividerItemDecoration用作Recycle ...

  3. RecyclerView万能分割线

    工具 public class RecycleViewDivider extends RecyclerView.ItemDecoration {private Paint mPaint;private ...

  4. Android RecyclerView万能分割线

    很久之前接触过RecyclerView,前段时间闲来无事用了下,结果发觉又被分割线伤了下.于是找了分代码,理解和完善,形成了适合我的一个个万能分割线工具类. 主要方法: /*** 看图说话:get I ...

  5. Android RecyclerView ItemDecoration 分割线

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/111302734 本文出自[赵彦军的博客] 文章目录 如何设置分割线 Divider ...

  6. android grid分割线,RecyclerView设置分割线---GridLayoutManager DividerItemDecoration

    给GridLayoutManager 设置简单的分割线 mBinding.rvWorkbench.addItemDecoration( DividerItemDecoration( activity, ...

  7. android view 虚线分割线,RecyclerView设置分割线---DividerItemDecoration

    官方提供的分割线处理方案,也是继承的RecyclerView.ItemDecoration实现的. divider.png 用法很简单,注释里面有demo.同时也可以通过自定义drawable来实现d ...

  8. Android RecyclerView设置分割线

    1.设置分割线代码 public class GridDividerItemDecoration extends RecyclerView.ItemDecoration {private static ...

  9. RecyclerView设置分割线的两种方法

    方法一.在item条目布局中直接在底部设置一个View,背景设置成想要的分割线颜色,高度设置成1dp, 这个方法很简单,只是是小聪明啦.... 方法二.在给recyclerview设置各种参数的时候 ...

  10. Android RecyclerView设置分割线 / 下拉加载 / 选项菜单进行增加删除动画

    首先看一下我的整个程序: 主类: package com.example.day02rk;import android.os.Bundle; import android.support.v4.con ...

最新文章

  1. ubuntu16.04 安装网易云音乐
  2. 静态移值编译的关键环境变量
  3. su: cannot set user id: Resource temporarily unavailable
  4. 语音增强原理之噪声估计
  5. 一些VR延迟优化方法
  6. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): dao.UserDao.selectU
  7. 【Docker系列教程之一】docker入门
  8. NET问答:如何理解 IEnumerableT 和 IQueryableT
  9. ubuntu 16.04下切换python版本小结
  10. javascript offsetLeft,Left,clientLeft 各种浏览器位置相关属性
  11. MySQL之Lock探索(二)
  12. NPS之Socks流量分析以及未授权复现
  13. STM32F429第二篇之推挽输出与开漏输出
  14. 【Auto Proxy】自研Go语言自动代理工具软件
  15. 武夫提笔——席卷世界Nodejs之初步对比:与opa各占几分春色?
  16. 计算机接入因特网有几种方式有哪些,简述几种因特网的接入方式?
  17. phython在file同时写入两个_Flink集成数据湖之实时数据写入iceberg
  18. 获取网页访问者的IP地址
  19. Mathtype7.4 嵌入至 Office 365
  20. 移动互联网App推广的十大难题

热门文章

  1. [注]打动我的50句广告语
  2. 八大流行的微服务架构设计模式探究
  3. PID控制器的离散化推导及其C语言实现
  4. python图片保存pdf_python将JPG图片转换为PDF
  5. 消防信号总线原理_消防联动工作原理
  6. 快速给PDF批量添加目录
  7. 明日之后 找不到服务器,明日之后服务器不一样怎么办_区服不同如何解决_软吧...
  8. Android城市公交查询系统,书签基于android平台的实时公交查询系统
  9. Windows下生成ssh密钥,并用ssh免密访问Linux服务器
  10. 使用pip无法完全卸载autoitlibrary,提示 we cannot accurately determine which files belong to it which would‘解决办法