1、ItemDecoration简介
Recyclerview是我们日常开发中使用频率比较高的的控件,而其中的ItemDecoration作为布局装饰又能很方便的帮助我们定义分割线,列表排行效果以及设置布局悬浮置顶效果等,所以有必要去了解ItemDecoration的诸多细节。
2、基本原理
我们先关注下实现RecyclerView.ItemDecoration必须要实现的三个方法,#getItemOffsets()用于在Item周围设置上下左右的间隙,然后我们可以使用#onDraw()在间隙绘制分割线以及其他图案等;而#onDrawOver()则是在RecyclerView布局上面绘制图案
public class MyDecoration extends RecyclerView.ItemDecoration{
/**
* step1 相当于itemView外还有一个矩形,我们可以自由在itemview上下左右设置空余部分,
通过outRect 的left,top,right,bottom 来进行设置,我们可在这块控件进行绘制
* 目标针对每一个item个体
*/
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
/**
* step2 在item间绘制 常用于绘制分割线
* 针对整个Recyclerview 绘制需要循环遍历item子布局 然后方能针对具体的item进行增加绘制
*/
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
}
/**
* 在item上绘制
*/
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}
2.1 getItemoffsets在RecyclerView源码中作用时机
manager#getItemDecorInsetsForChild
为指定view计算分割线矩形
Rect getItemDecorInsetsForChild(View child) {
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams)child.getLayoutParams();
if (!lp.mInsetsDirty) {
return lp.mDecorInsets;
} else if (this.mState.isPreLayout() && (lp.isItemChanged() || lp.isViewInvalid())) {
return lp.mDecorInsets;
} else {
Rect insets = lp.mDecorInsets;
insets.set(0, 0, 0, 0);
int decorCount = this.mItemDecorations.size();
for(int i = 0; i < decorCount; ++i) {
this.mTempRect.set(0, 0, 0, 0);
((RecyclerView.ItemDecoration)this.mItemDecorations.get(i)).getItemOffsets(this.mTempRect, child, this, this.mState);
insets.left += this.mTempRect.left;
insets.top += this.mTempRect.top;
insets.right += this.mTempRect.right;
insets.bottom += this.mTempRect.bottom;
}
lp.mInsetsDirty = false;
return insets;
}
}
// 测量的时候 当作padding值放入其中
public void measureChild(@NonNull View child, int widthUsed, int heightUsed) {
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams)child.getLayoutParams();
Rect insets = this.mRecyclerView.getItemDecorInsetsForChild(child);