recyclerView-自定义itemDecoration详解

时间:2022-09-07 11:57:22
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) {