# LogisticsDemo **Repository Path**: trydamer/logistics-demo ## Basic Information - **Project Name**: LogisticsDemo - **Description**: Android recycler itemdecoration logistics - **Primary Language**: Kotlin - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: https://gitee.com/trydamer/logistics-demo - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-07-16 - **Last Updated**: 2023-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## RecyclerView.ItemDecoration    ### 一、前言 前段时间刚接触到RecyclerView的ItemDecoration,于是想学习一下。下文将围绕“物流时间线”对ItemDecoration进行详细的分析,“物流时间线”的效果图如下:
### 二、ItemDecoration
顾名思义,ItemDecoration是对列表进行装饰的,简单的列表样式可以直接在布局文件中就搞定了,例如分割线。但当需求比较复杂时,例如“物流”这种列表就不适用了。
ItemDecoration的原理是通过改变item的边距从而腾出空间,然后在这些空间中绘制装饰的内容。所以如果要使用ItemDecoration,需要对自定义View有一些了解,最起码会用canvas+paint绘制一些简单的东西。
#### 2.1 ItemDecoration的关键方法
ItemDecoration有几个比较重要的方法,下面我们逐一分析这些方法的作用和用法。
#### 2.1.1 getItemOffsets
```kotlin
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
)
```
这个方法主要是设置Item的上下左右边距,直接设置outRect的上下左右就可以了。例如设置左边边距为50像素:outRect.left= 50。具体效果可以看我盗的这张图,如下:

(注:Rect的set方法参数:set(left, top, right, bottom))
我们在这个方法中,设置了列表的边距,多出来的空间就可以用来绘制装饰的东西了。
#### 2.1.2 onDraw
```kotlin
override fun onDraw(
c: Canvas,
parent: RecyclerView,
state: RecyclerView.State
)
```
这个方法和View的onDraw一样,画就完了。不同的是,在这个方法里应该遍历parent的子view来画,即为每一个item都加上装饰。代码如下:
```kotlin
for (i in 0 until parent.childCount) {
...
}
```
#### 2.1.3 onDrawOver
```kotlin
override fun onDrawOver(
c: Canvas,
parent: RecyclerView,
state: RecyclerView.State
)
```
这个方法也是绘制的,和onDraw唯一的区别就是调用顺序,简单来说:
- onDraw 绘制的东西如果与item重叠,则重叠区域被item覆盖;
- onDrawOver 绘制的东西如果与item重叠,则重叠区域被onDrawOver覆盖。
一般来说只需要重写onDraw方法即可,onDrawOver用得比较少。
### 2.2 实战
#### 2.2.1 需求分析
参考了几大网购平台的App物流页面,大多都是在列表的左边进行装饰。每个item都有一个小圆点或图标或大圆点,而且都与item的第一行文字水平对齐(注意,是item的第一行文字!!!),如下图所示:

这是一个难点,也是唯一有点难度的地方,因为我们需要“精通”几何学才能解决这个问题,当然,能够熟练地使用“几何桶”也是可以的,哈哈哈。有问题就要解决问题,我们写代码的目的就是先写bug,再解决bug,如下图:

上图中,就是没有计算好坐标,所以出现了问题。
#### 2.2.2 实现
经过我一通胡编乱造的分析后,可以确定几个问题:
- item留出左边的空间
- 确定每个节点的y坐标
- 绘制时间线和节点圆
因此我们在getItemOffsets方法中,只要左边有空间即可,代码如下:
```kotlin
override fun setOutRect(outRect: Rect) {
outRect.set(dp2px(DECORATION_START), 0, 0, 0)
}
```
这样便在item的左边腾出一些空间(30dp)来绘制时间线了,先来看一下添加ItemDecoration和不添加的区别: