本次因为一直在用RecyclerView LinearLayoutManager对应的decoration,目前处理GridLayout时由于要处理左右侧的item的边距和蹭的Item边距不同,就回顾一下RecyclerView 对ItemDecoration的学习。
由于不是ListView和GridView,RecyclerView把这个称为Item的装饰,所以分隔线的处理就交给ItemDecoration来处理。
RecyclerView设置ItemDecoration调用如下方法:
recyclerView.addItemDecoration()
ItemDecoration类主要是三个方法:
public void onDraw(Canvas c, RecyclerView parent, State state)
public void onDrawOver(Canvas c, RecyclerView parent, State state)
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
- getItemOffsets 中为 outRect 设置的4个方向的值,将被计算进所有 decoration的尺寸中,而这个尺寸,被计入了 RecyclerView 每个 item view 的 padding 中
- 在 onDraw 为 divider 设置绘制范围,并绘制到 canvas 上,而这个绘制范围可以超出在 getItemOffsets 中设置的范围,但由于 decoration 是绘制在 child view 的底下,所以并不可见,但是会存在overdraw
- decoration 的 onDraw,child view 的 onDraw,decoration 的 onDrawOver,这三者是依次发生的
- onDrawOver 是绘制在最上层的,所以它的绘制位置并不受限制
所以ItemDecoration 不仅仅限制于作Divider,还可以做一些Item的装饰,比如一些电商的热卖标识,提醒标记都可以用ItemDecoration来做,关于StickyHeader也可以用ItemDecoration做。
关于分组就是与外部交换数据确实group位置,并在group组内第一个数据上方添加decoration。具体这一块可以直接参考RecyclerView之ItemDecoration由浅入深。讲得很清楚,还把stickyHeader实现了。
后面实质上是数学的计算来设置每个item的left, top, right, bottom的具体数值。由于麻烦是Grid的item的边距,一般都是每个item的上下和左右边距是一样的,非常对称,边缘部分没有边距,正好项目以上有这个itemdecoration,所以共享出来,应该是之前网上找好,就是这个文章里的 Android RecyclerView 间距全适配,不过我是在github上找的。我贴下我自己的效果,没有使用边缘边距。
实现代码
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
上面代码计算还是非常巧妙的,代码少体现的则是边距和位置的关系计算各种分多少spacing.
以下是参考资料,已经讲得非常清楚,效果如下。
参考连接
RecyclerView 自定义 ItemDecoration
bignerdranch simple item decoration
RecyclerView之ItemDecoration由浅入深
stackoverflow issue
RecyclerView定制:通用ItemDecoration及全展开RecyclerView的实现
深入理解 RecyclerView 系列之一:ItemDecoration