ItemDecoration

getItemOffsets

为了给绘制 Decoration 腾出绘制区域,RecyclerView 通过调用 ItemDecoration 的 getItemOffsets,获取需要的绘制区域尺寸,保存到 RecyclerView.LayoutParams 的 mDecorInsets 变量里。

RecyclerView measure 和 layout 过程中会考虑到 mDecorInsets,也就是说除了 Padding,Margin 之外,RecyclerView 还增加了 mDecorInsets 进行布局。mDecorInsets 的作用Margin 比较相似。

onDraw,onDrawOver

onDraw 和 onDrawOver 都是绘制 Decoration,区别在于,onDraw 在 RecyclerView 绘制 Children 之前,onDrawOver 在 RecyclerView 绘制 Children 之后。

以 DividerItemDecoration 为例分析

getItemOffsets 根据方向,为 outRect 的 bottom 或者 left 设置了 mDivider 的高度或宽度。

getItemOffsets

onDraw 过程,根据方向,调用 drawVertical 或者 drawHorizontal。

onDraw

以 drawVertical 为例进行分析。

drawVertical

先调用 RecyclerView 的 getDecorationBoundsWithMargins 获取到一个 Rect mBounds。

根据 bottom 和 mDivider 的 height,得到 Decoration 绘制区域。

getDecoratedBoundsWithMaginsInt

RecyclerView 的 getDecorationBoundsWithMargins 其实调用的是 RecyclerView 的 static 方法 getDecoratedBoundsWithMarginsInt。可以看到,outBounds 根据 View 的位置参数,margin 以及 insets 生成。这个 insets 与前面 getItemOffset 获取到的 Rect 属性相同。

自己定制

综上而言,要定制自己的 ItemDecoration 其实非常简单,只需要 override getItemOffsets 函数, 为 View 的上下左右腾出绘制区域。然后在 onDraw 或者 onDrawOver 时,通过 RecyclerView.LayoutParams 和 View 的位置信息,计算绘制区域,绘制 Decoration 即可。

获取 View 布局参数等过程可以参考 DividerItemDecoration。

思考

RecyclerView 添加 ItemDecoration 的方法是 addItemDecoration 而不是 setItemDecoration,说明一个 RecyclerView 可以有多个 ItemDecoration。一般来说,一个 Decoration 已经够用了。但当有多个 ItemDecoration 时,它们的 ItemOffsets 是重叠(最终大小由最大的 ItemOffset 决定)?还是相加呢?

你可能感兴趣的:(ItemDecoration)