recyclerView-自定义itemDecoration详解

时间:2022-09-07 11:52:57
public class SectionDecoration extends RecyclerView.ItemDecoration {

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
}

一共就提供2个方法

方法一

自定义itemDecoration
public class MyItemDecoration extends RecyclerView.ItemDecoration {

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

System.out.println("left = " + outRect.left);
System.out.println("top = " + outRect.top);
System.out.println("right = " + outRect.right);
System.out.println("bottom = " + outRect.bottom);
// super.getItemOffsets(outRect, view, parent, state);
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}

getItemOffsets 参数一 outRect的默认值是 0 :
01-23 17:33:31.727 24556-24556/com.adnonstop.brvah I/System.out: left = 0
01-23 17:33:31.727 24556-24556/com.adnonstop.brvah I/System.out: top = 0
01-23 17:33:31.727 24556-24556/com.adnonstop.brvah I/System.out: right = 0
01-23 17:33:31.727 24556-24556/com.adnonstop.brvah I/System.out: bottom = 0

修改outRect
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(60, 60, 60, 60);
System.out.println("left = " + outRect.left);
System.out.println("top = " + outRect.top);
System.out.println("right = " + outRect.right);
System.out.println("bottom = " + outRect.bottom);
// super.getItemOffsets(outRect, view, parent, state); 一定要注销掉;因为 父类执行的是 outRect.set(0,0,0,0);
}


outRect的值
01-23 17:37:46.037 31451-31451/com.adnonstop.brvah I/System.out: left = 60
01-23 17:37:46.037 31451-31451/com.adnonstop.brvah I/System.out: top = 60
01-23 17:37:46.037 31451-31451/com.adnonstop.brvah I/System.out: right = 60
01-23 17:37:46.037 31451-31451/com.adnonstop.brvah I/System.out: bottom = 60

方法一作用,类似于给每一个Item布局设置margin或padding

recyclerView-自定义itemDecoration详解




完整定义

linearlayoutManager的分割线

public class MyItemDecoration extends RecyclerView.ItemDecoration {

private final Drawable drawable;

public MyItemDecoration(Context context) {
drawable = ContextCompat.getDrawable(context, R.drawable.item_divider);
}

/**
* 如果 只需要设置linearlayoutmanager 的分割线,那么只需要设置outRect.top 值即可。
* @param outRect
* @param view
* @param parent
* @param state
*/
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

/**
* 跳过索引为0的item
*/
if (parent.getChildLayoutPosition(view) < 1) {
return;
}
/**
* 设置item的相对偏移量
*/
outRect.top = drawable.getIntrinsicHeight();
}

/**
* 切记: 从 索引为 1 的 item 开始画
*
* @param c
* @param parent
* @param state
*/
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {

int childCount = parent.getChildCount();

int rightV = parent.getWidth();

for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

int leftV = parent.getPaddingLeft() + child.getPaddingLeft();

//从索引的为1 的item开始绘制的。
int bottomV = child.getTop() - params.topMargin;


int topV = bottomV - drawable.getIntrinsicHeight();


drawable.setBounds(leftV, topV, rightV, bottomV);
drawable.draw(c);
}
}
}


Drawable使用shape绘制: item_divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="10dp" />
<solid android:color="@color/colorAccent" />
</shape>

recyclerView-自定义itemDecoration详解


当条目总数为0时,不会调用itemDecotation的方法的。



当itemCount = 3,看itemDecoration方法执行的顺序

02-10 12:28:14.566 6626-6626/com.qingmu.footerrecyclerview I/SectionDecorationchild: getItemOffsets: = 1
02-10 12:28:14.566 6626-6626/com.qingmu.footerrecyclerview I/SectionDecorationchild: getItemOffsets: = 2
02-10 12:28:14.576 6626-6626/com.qingmu.footerrecyclerview I/SectionDecorationchild: getItemOffsets: = 3
02-10 12:28:14.576 6626-6626/com.qingmu.footerrecyclerview I/SectionDecorationchild: onDraw: = 3
02-10 12:28:15.026 6626-6626/com.qingmu.footerrecyclerview I/SectionDecorationchild: onDraw: = 3

显然是根据itemCount执行itemCount次getItemOffSets,然后再执行itemCount-1次onDraw。


  //一般情况下params.TopMargin = 0 ,所以bottomV = child.getTop();
int bottomV = child.getTop() - params.topMargin;//这个params.TopMargin并非getItemOffSets的outRect.top = topGap;


 /**
* y值越小,越靠上
* bottomV 注定大于 TopV
*
* @param c
* @param parent
* @param state
*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {