RecyclerView学习--自定义ItemDecoration

xiaoxiao2021-09-19  119

RecyclerView无法像ListView直接设置分割线,但是提供了ItemDecoration类来设置,有一个实现类DividerItemDecoration提供了一个简单的分隔线,如果想自定义可以继承ItemDecoration,参考DividerItemDecoration来写。

1.主要实现方法

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.具体的实现

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(); } }

底部空出了这个Drawable高度的距离,也就是红色的部分

这个是垂直方向的LinearLayoutManager的绘制方式,如果是水平或者GridLayoutManager要注意考虑设置 间隔线范围的位置是底部还是右边 GridLayoutManager要注意边界的Item可能有的不需要加分隔,要注意。

有什么意见和错误欢迎提出。

转载请注明原文地址: https://www.6miu.com/read-4823628.html

最新回复(0)