上一篇文章讲了如何使用ItemDecoration去实现RecyclerView的万能间距,可是很多时候我们的需求里还会有分割线,有时候既要有合适的间距,也要有分割线,这种需求多出现在列表中,也就是网格布局中,这个时候就需要我们自己去画了,如果你天真的把分割线加到布局里,那效果将会是奇丑无比。。。直接看代码吧:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;import com.btime.base_utilities.BTimeUtils;/*** Created by kangbaibai on 2018/5/14.* 网格布局分割线*/public class GovAffMatrixItemDecoration extends RecyclerView.ItemDecoration {private Paint mPaint; //如果需要用画笔手绘private Drawable mDrawableDivider; //如果需要绘制给定的drawableprivate int mPaintDividerLength = 1; //分割线宽度或高度private DrawType drawType; //用画笔或者特定的drawable绘制private int spanCount = 1; //网格布局的列数或行数,默认为一/*** 注意:列表的方向* LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL*/private int mOrientation;private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; //系统默认的分割线/*** 自定义分割线** @param context     上下文* @param orientation 列表方向* @param drawableId  分割线图片*/public GovAffMatrixItemDecoration(Context context, int orientation, int drawableId) {if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {throw new IllegalArgumentException("请输入正确的参数!");}mOrientation = orientation;if (drawableId == -100) {final TypedArray a = context.obtainStyledAttributes(ATTRS); //获取系统的样式mDrawableDivider = a.getDrawable(0);a.recycle();} else {mDrawableDivider = ContextCompat.getDrawable(context, drawableId);}drawType = DrawType.USEDRAWABLE; //表明使用特点的drawable绘制}/*** @param context     上下文* @param orientation 列表方向*/public GovAffMatrixItemDecoration(Context context, int orientation) {this(context, orientation, -100);}/*** 自定义分割线** @param orientation   列表方向* @param dividerHeight 分割线高度* @param dividerColor  分割线颜色*/public GovAffMatrixItemDecoration(int orientation, int dividerHeight, int dividerColor) {if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {throw new IllegalArgumentException("请输入正确的参数!");}mOrientation = orientation;if (dividerHeight != -100) {//分割线高度mPaintDividerLength = dividerHeight;}//创建特定画笔mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(dividerColor);mPaint.setStyle(Paint.Style.FILL);//表明绘制用paintdrawType = DrawType.USEPAINT;}/*** 自定义分割线** @param orientation  列表方向* @param dividerColor 分割线颜色*/public GovAffMatrixItemDecoration(int orientation, int dividerColor) {this(orientation, -100, dividerColor);}/*** get Item Offsets:获得item的偏移量。* 通过方法名得知此方法用来控制item的偏移** @param outRect* @param view* @param parent* @param state*/@Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {super.getItemOffsets(outRect, view, parent, state);if (parent.getLayoutManager() instanceof GridLayoutManager) {GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();spanCount = gridLayoutManager.getSpanCount();}/*** 列表的方向为横向,画分割线就是纵向的,需要确定的是child的右边偏移值* 留出空间画分割线*/if (this.mOrientation == LinearLayoutManager.HORIZONTAL)switch (drawType) {case USEPAINT:outRect.set(0, 0, mPaintDividerLength, 0);break;case USEDRAWABLE:outRect.set(0, 0, mDrawableDivider.getIntrinsicWidth(), 0);break;}/*** 列表的方向为纵向,画分割线就是横向的,需要确定的是child的下边偏移值* 留出空间画分割线*/else if (this.mOrientation == LinearLayoutManager.VERTICAL)switch (drawType) {case USEPAINT:outRect.set(mPaintDividerLength, 0, 0, mPaintDividerLength);break;case USEDRAWABLE:outRect.set(mDrawableDivider.getIntrinsicHeight(), 0, 0, mDrawableDivider.getIntrinsicHeight());break;}}/*** 绘制分割线** @param c* @param parent* @param state*/@Overridepublic void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {super.onDraw(c, parent, state);if (mOrientation == LinearLayoutManager.VERTICAL) {//列表是纵向的,需要绘制横向的分割线drawHorizontal(c, parent);drawVertical(c, parent);} else {//列表是横向的,需要绘制纵向的分割线drawVertical(c, parent);}}/*** 绘制横向 item 分割线。左、上、右都是可计算的,下需要获取给定的高度值** @param canvas* @param parent*/private void drawHorizontal(Canvas canvas, RecyclerView parent) {//左边:到父容器的left内间距位置值final int left = parent.getPaddingLeft();//右边:到父容器的right内间距位置值final int right = parent.getMeasuredWidth() - parent.getPaddingRight();final int childSize = parent.getChildCount();//循环绘制每条分割线//因为每次绘制会以父布局的宽为长度,所以每行只需绘制一次,在此计算出需要绘制的次数int drawSize = (childSize / spanCount) + ((childSize % spanCount > 0) ? 1 : 0);for (int i = 1; i < childSize; i++) {if (i % spanCount == 0) {final View child = parent.getChildAt(i - 1);RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();//上边:具体的某条分割线的左边以child的(bottom+bottomMargin)位置值final int top = child.getBottom() + layoutParams.bottomMargin;//下边:根据类型判断int bottom;switch (drawType) {case USEPAINT://构造方法声明使用画笔绘制//下边:top加上分割线的高度bottom = top + mPaintDividerLength;if (mPaint != null) {canvas.drawRect(left, top, right, bottom, mPaint);}break;case USEDRAWABLE://构造方法声明使用drawableif (mDrawableDivider != null) {//下边:top加上分割线的高度bottom = top + mDrawableDivider.getIntrinsicHeight();mDrawableDivider.setBounds(left, top, right, bottom);mDrawableDivider.draw(canvas);}break;}}}}/*** 绘制纵向 item 分割线。上、下、左都是可计算的,右侧需要获取给定的宽度值** @param canvas* @param parent*/private void drawVertical(Canvas canvas, RecyclerView parent) {//上边:到父容器的top内间距位置值
//        final int top = parent.getPaddingTop();
//        //下边:到父容器的bottom内间距位置值
//        final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();final int childSize = parent.getChildCount();//循环绘制每条分割线for (int i = 0; i < childSize - 1; i++) {if (i % spanCount == 0 || i % spanCount == 1) {final View child = parent.getChildAt(i);//获取child的布局参数RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();final int top = child.getTop() + BTimeUtils.DisplayUtil.dip2px(8);final int bottom = child.getBottom() - BTimeUtils.DisplayUtil.dip2px(8);//左边:具体的某条分割线的左边以child的(right+rightMargin)位置值final int left = child.getRight() + layoutParams.rightMargin;//右边:根据类型判断int right;switch (drawType) {case USEPAINT://构造方法声明使用画笔绘制//右边:left加上分割线的宽度right = left + mPaintDividerLength;if (mPaint != null) {canvas.drawRect(left, top, right, bottom, mPaint);}break;case USEDRAWABLE://构造方法声明使用drawableif (mDrawableDivider != null) {//右边:left加上分割线的宽度right = left + mDrawableDivider.getIntrinsicWidth();mDrawableDivider.setBounds(left, top, right, bottom);mDrawableDivider.draw(canvas);}break;}}}}public static enum DrawType {USEPAINT(1),//用自定义颜色的画笔画USEDRAWABLE(2); //用特定的drawable画private final int type;DrawType(int type) {this.type = type;}public int getType() {return type;}}
}
如果既要间距又想画分割线,那就把两篇文章的代码结合起来,很轻松就可以实现啦!赶快动手吧!

RecyclerView之利用ItemDecoration实现万能分割线相关推荐

  1. Android RecyclerView万能分割线

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

  2. RecyclerView的万能分割线

    效果图: 使用方法: 添加默认分割线:高度为2px,颜色为灰色 mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, Lin ...

  3. android 分割线布局,Android RecyclerView网格布局(支持多种分割线)详解(2)

    记录了下RecyclerView的使用方法,并且讲述了线性布局列表的使用方法,在此基础上加上了万能分割线,支持颜色分割线和图片分割线,同时支持对分割线设置线宽. 这篇是总结一下网格布局的使用,同样也支 ...

  4. day5 RecyclerView、多布局、万能适配器

    RecyclerView 概义 RecyclerView是什么 从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加 ...

  5. RecyclerView万能分割线

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

  6. Android RecyclerView 向上偏移解决、添加自定义分割线,瀑布流,ScrollView嵌套RecyclerView滑动卡顿

    向上偏移解决 android:focusableInTouchMode="true" android:focusable="true" android:fill ...

  7. android item三种,Android RecyclerView中的ItemDecoration的几种绘制方法

    如题,我们使用recyclerview的时候,如果没有设置显示条目的margin,或者padding的话,是没有分割线效果的. 那么除去使用margin或padding,其余的方法是用itemdeco ...

  8. RecyclerView中绘制不相同的分割线

    在绘制RecyclerView的分割线时我们通常是设置系统属性的android:listDivider为自定义的样式,然后再通过TypedArray获取一个drawable对象,通过回执drawabl ...

  9. android 头部分割线,ItemDecoration实践之分割线与粘性头部

    RecyclerView提供了良好的设计,将各部分功能的实现都拆解开,方便自定义,虽然加大了使用难度,但是却大大的增加了可扩展性,稍微会使用之后,扩展起来非常的舒心. 功能:适用于以下几种布局的分割线 ...

最新文章

  1. 知识图谱简史:从1950到2019
  2. 重置outlook 2010
  3. 微信小游戏 Egret开发数据域官方Demo下载地址
  4. 【FFmpeg】ffmpeg 命令查询二 ( 比特流过滤器 | 可用协议 | 过滤器 | 像素格式 | 标准声道布局 | 音频采样格式 | 颜色名称 )
  5. 进程互斥的要求与实现方法
  6. Node.js中package.json中库的版本号详解(^和~区别)
  7. 阿里启动NASA计划创造新经济核心科技
  8. 人生这道题,要该怎么做?
  9. 10款国外知名杀软的免费试用版(三个月、半年或一年)
  10. LoRa协议学习工具
  11. ERP学习 之 财务管理
  12. 【使用pycharm管理github仓库】github代码版本控制
  13. Mongodb索引及explain
  14. 几何学在计算机中的应用,探析坐标几何的应用意义及其在计算机中的实现
  15. 【每日一短语】首席芭蕾舞演员
  16. 使用POI读取大量数据EXCEL文件,并解析成自定义javaBean
  17. 读取db服务器信息出错,尝试读取foxpro dbf并获取错误:无法初始化链接服务器的OLE DB提供程序“MSDASQL”的数据源对象“(空)”...
  18. Windows Update有用吗
  19. 监听Home键和锁屏键
  20. 将一个十六进制“字符串”转换为十进制数值的问题

热门文章

  1. 时代潮流-云原生数据库的崛起
  2. 《这个历史挺靠谱·上·袁腾飞讲中国史》读后感
  3. BD电影搜索-自定义过滤器
  4. FlyThings OS:基于Linux实现现代化人机交互体验的新嵌入式操作系统
  5. 诗词创作[2] 赠春
  6. google的RateLimiter限流器的使用
  7. Dubbo+zookeeper
  8. 操作BLOB、CLOB、BFILE
  9. 用python爬取头条文章_AI第四课:Python爬取今日头条文章
  10. JS中的CommonJS和AMD