ItemDecoration

2018-03-21  本文已影响25人  luckyzhangx

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 决定)?还是相加呢?

上一篇 下一篇

猜你喜欢

热点阅读