Recyclerview添加自定义的虚线分割线

时间:2024-03-21 09:53:50

工作需要,recyclerView添加虚线分割线,想实现的效果是这样的:

Recyclerview添加自定义的虚线分割线


需要自定义DashlineDecoration继承自RecyclerView.ItemDecoration,其中有三个方法:

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)

下面我想先解释一下我对这三个方法的理解,如有错误,欢迎指正!

onDraw方法,应该很熟悉了,自定义View的时候经常使用的一个方法,顾名思义,就是用来才画布canvas上绘制图像的方法。那么,画,应该怎么去画?画在哪里?等等问题需要我们想明白。怎么画?有人肯定要说当然是用Paint去画喽!对,但是你需要先弄清楚你自己的需求,比如我的项目里,我需要画线,而且是虚线,画距离屏幕左右两侧分别是10dp的线,宽度呢,是2px就够了。画在哪里呢?这里就要与onDrawOver方法进行比较了。为什么会有两个画的方法呢?看onDrawOver的名字应该也能猜到了,onDraw肯定是与onDrawOver对立的。over这个词,解释为上面,那么是什么上面呢?recyclerview嘛,在画布上只有两个东东,一个是item列表,一个是divider分割线。现在我们是要画分割线,当然就是对应在item上面喽!那么也就知道了onDraw方法是画在了列表的下面。


既然onDraw画在item下面了,那么divider不是就不可见了吗?这时候就要来看getItemOffsets方法了。这个方法是干嘛的,我的理解就是来获取到item之间的间隔的。看他的第一个参数,是一个Rect对象,叫做outRect,我们可以通过它来设置item的间隔,怎么设置呢?使用outRect.set(int,int,int,int)方法或者outRect.set(Rect)方法都行,随便你喜欢。

/**
 * Set the rectangle's coordinates to the specified values. Note: no range
 * checking is performed, so it is up to the caller to ensure that
 * left <= right and top <= bottom.
 *
 * @param left   The X coordinate of the left side of the rectangle
 * @param top    The Y coordinate of the top of the rectangle
 * @param right  The X coordinate of the right side of the rectangle
 * @param bottom The Y coordinate of the bottom of the rectangle
 */
public void set(int left, int top, int right, int bottom) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
}

看到这个方法的源码,注意看注释,我们可以知道我们设置的四个参数其实就是分割线divider的矩形,这么说不准确,应该是允许divider显示的矩形区域。不明白?我来给你解释。


我们知道每个item之间都有一个小的缝隙用来放分割线,注意这里的缝隙其实并不是分割线,但是某些情况下你可以就把它当做分割线来用(比如当你需要绘制颜色和recyclerview的背景色相同的实线分割线时)。这个缝隙其实就是一个矩形Rect,他有宽和高,width = bottom - top,height = right - left,一般我们直接设置yop和right为0即可。divider只能画在这个缝隙之中才能显示,如果没有就会被隐藏了,其实是被item给遮挡住了,这个结论有大神已经验证过,如果你不信,那么你可以设置recyclerview的background为透明色去看一下。


说完了getItemOffsets方法,我想大家应该明白onDraw画的分割线怎么可见了吧?就是画在item之间的小缝隙中。


我的需求是画虚线,在虚线的gap处的颜色就是item的颜色(这里是白色)。但是如果使用onDraw方法画虚线并放在getItemOffsets设置的矩形里,它的gap处就会是recyclerview的背景色(这里是背景灰),显然需求对不上。那么怎么办呢?接着往下看。


不得不提一下onDrawOver了,这个方法不是把分割线画在item下面,而是在item上面绘制,也就是说,我画好了各个item,然后在item上层绘制divider,这样onDrawOver绘制的东东就一定可见了。要想绘制出想要的效果,我不希望绘制的divider后还有一个item之间的小缝隙,所以我需要在getItemOffsets方法中设置outRect.set(0,0,0,0),这样,item之间就没有缝隙了。


说明白了上面的三个方法和需求分析,在捋一遍思路,其实就是要重写onDrawOver和getItemOffsets两个方法。getItemOffsets中设置没有缝隙,onDrawOver中绘制虚线。


画线,我们常用的就是Path,首先初始化一个Path对象,然后使用moveTo和lineTo两个方法先设置一条线的路径,然后调用canvas.drawPath(path, paint);方法画线就行了。虚线呢?Paint允许我们我们使用虚线

paint.setPathEffect(effects);

还需要使用PathEffect对象,

PathEffect effects = new DashPathEffect(new float[]{15, 10, 15, 10}, 5);

float数组的四个数是指的先画15px的实线,然后画10px的空白再画15px的实线,再画10px的空白...一次规律循环。后面的“5”指的是第一条实线要距离开始位置多远。

好了,最后调用

c.drawPath(path, paint);
即可。

相关文章