RecyclerView learning - Custom ItemDecoration

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/One_Month/article/details/83000035

RecyclerView not like ListView directly dividing line, but provides ItemDecoration class setting, there is a class that implements DividerItemDecoration provides a simple dividing line, if you want to customize can inherit ItemDecoration, reference DividerItemDecoration to write.

Renderings, I wrote a shape
1. Major Implementation

public class MyLinearDecoration extends RecyclerView.ItemDecoration {
	//绘制自定义的分隔线,这个绘制和item的View属于同一位面,分隔线太大会阻挡视图
	//这个绘制大小要配合getItemOffsets中设置的分隔线空间
    @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);
    }

    //Over是 在...之上的意思,所以他是在onDraw绘制位面的上一层进行绘制,他和onDraw相当于2层画布
	@Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
    }
}

2. Specific implementation

public class MyLinearDecoration extends RecyclerView.ItemDecoration {
    Paint paint;
    Drawable drawable;
    Rect mBounds = new Rect();
    public MyLinearDecoration(Drawable drawable) {
        super();
        paint = new Paint();
        paint.setColor(Color.RED);
        this.drawable = drawable;
    }

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

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c,parent,state);
        int right = 0;
        int left = 0;
        c.save();
        //这个if else是参照DividerItemDecoration,可以提高点性能,减少画布大小,
        //如果recyclerView设置了Padding,我们没必要获取整个画布,获取减去padding的
        //才是我们真正能够操作的画布
        if (parent.getClipToPadding()) {
            int top = parent.getPaddingTop();
            int bottom = parent.getPaddingBottom();
            left = parent.getPaddingLeft();
            right = parent.getWidth()-parent.getPaddingRight();
            c.clipRect(left,top,right,parent.getHeight() - bottom);
        }else{
            left = 0;
            right = parent.getWidth();
        }
        
        //下面的操作,遍历Item,为Item绘制想要的分隔线
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view = parent.getChildAt(i);
            
            //获取这个Item的包含了Decoration和Margin的范围,相当于加上getItemOffsets设置的大小和Margin大小后,
            //这个Item的左,上,右,下的坐标
            parent.getDecoratedBoundsWithMargins(view, mBounds);
            
            //这个注释掉的是按照我自己的想法设置的绘制边界,测试也没问题,我从示例中得出结论是
            //mBounds得到的就是每个RecyclerView的Item加上间隔和margin后的最终所处的四个方位的坐标,
            //那么我们绘制Decoration的底部
            //就应该是mBounds.bottom,高度就应该是底部坐标减去分隔线的高度
			//final int bottom = mBounds.bottom;
            //final int top = mBounds.bottom - drawable.getIntrinsicHeight();
            
            //DividerItemDecoration中的示例是加了一个Math.round(view.getTranslationY()),这个获取的是这个View相对于他个
            //getTop的距离,我Debug查看了获取的值,一直为0,暂时没太明白这样写的意思。
            final int bottom = mBounds.bottom + Math.round(view.getTranslationY());
            final int top = bottom - drawable.getIntrinsicHeight();
            
            //这是我在构造器中传入的Drawable要绘制到的画布的范围
            drawable.setBounds(left, top, right, bottom);
            drawable.draw(c);
        }
        c.restore();
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        //这个设置的意思是,在Item的底部加上一段距离,让分隔线画在这个范围
        //不设置的话,分隔线会画到Item的视图上,造成重合
        //如果你的onDraw没有给出自己的实现,只是通过这个方法设置一块区域,那么也会
        //出现一段距离,背景色是这个界面的背景色
        outRect.bottom = drawable.getIntrinsicHeight();
    }
}

The bottom of the air out from the Drawable height, which is the red part

This is the draft mode LinearLayoutManager in the vertical direction, if it is to be noted that the horizontal or GridLayoutManager consider setting
the position of the partition lines is a bottom or right range
GridLayoutManager Item to be noted that the boundary may not need to add any partition, to pay attention.

What wrong views and welcome.

Guess you like

Origin blog.csdn.net/One_Month/article/details/83000035