RecyclerView.ItemDecoration(笔记)

来源:互联网 发布:软件系统 吞吐量测试 编辑:程序博客网 时间:2024/06/02 13:48

今天对RecyclerView.ItemDecoration做了蛮多的理解,赶紧记下来,一直在思考分割线与item间的关系,后来模仿着做了很多的调整测试,才大概弄懂了。

这是一个分割线的绘制,通过multRecyclerView.addItemDecoration(new ItemDecoration(this));就可以将其显示出来。

public class ItemDecoration extends RecyclerView.ItemDecoration{private static final int[] ATTRS = new int[]{android.R.attr.listDivider};private Drawable mDivider;public ItemDecoration(Context context){final TypedArray typedArray = context.obtainStyledAttributes(ATTRS);mDivider = typedArray.getDrawable(0);typedArray.recycle();}@Overridepublic void onDraw(Canvas c, RecyclerView parent, State state) {// TODO Auto-generated method stubsuper.onDraw(c, parent, state);drawVertical(c , parent);}private void drawVertical(Canvas c, RecyclerView parent) {// TODO Auto-generated method stub//recyclerview左边界+paddingleft后的位置final int left = parent.getPaddingLeft();//右边界-paddingright后的位置final int right = parent.getWidth() - parent.getPaddingRight();final int count = parent.getChildCount();for(int i = 0 ; i < count ; i ++){final View childView = parent.getChildAt(i);final RecyclerView.LayoutParams params = (LayoutParams) childView.getLayoutParams();final int top = childView.getBottom() + params.bottomMargin ;//top加上divider的高度 final int bottom = top + mDivider.getIntrinsicHeight();mDivider.setBounds(left , top , right , bottom);mDivider.draw(c);}}@Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {// TODO Auto-generated method stubsuper.getItemOffsets(outRect, view, parent, state);outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());}}


图:





这里面分成两个地方,一个是onDraw(),另一个则是getItemOffsets()。

首先我们在onDraw里去画分割线,然后在getItemOffsets里去设置item的显示(这里要作个说明,在这部分代码里是让item给分割线留出位置,而这个位置也刚好是分割线的高度。那么其实这个item的范围实际上是可以大于我们自己本身自己的chidView,做一些修改来看下:

以下只提供修改的代码,其它的没有说明则表示不变:

只修改getItemOffsets()

(1)outRect.set(0, 0, 0, 0);


这里我们可以看到没有分割线,当你不写getItemOffsets()方法的时候,它也是没有显示,那么这里其实是分割线通过onDraw()已经画好了,只是因为我们没有给分割线预留了空间,所以它被藏在了后面。

(2)outRect.set(100, 0, 0, 0);


所以我们试着往右移,从这里我们可以看到分割线实际是在后面的。

(3)outRect.set(100, 0, 0, 100);


outRect.set(100, 100, 0, 0);


先不管分割线,因为我们的分割线是设置固定在childView的下方的,不是根据item。从这些就可以看出,在getItemOffsets()里我们对item的尺寸进行了设置(我们要区分这里的item和我们自己设置的R.layout.item里的是有区别的。这里的childView就是我们自己设置的R.layout.item,而item就是这外层的整体。所以当我们在进行outRect.set(left,top ,right , bottom)的时候,就类似于在设置childView相对于item的padding。)。

修改onDraw()

(1)final int top = childView.getBottom() + params.bottomMargin + 50;


这里我们将分割线的top在原来上+50,那么它绘制出来的话就是在原来的基础上,往下移动50个像素。

那么我们可以进一步操作,来看的更明显些:

final int top = childView.getBottom() + params.bottomMargin + 360 ;
outRect.set(50, 0, 0, mDivider.getIntrinsicHeight());


我们先把childView往右移一下,这样我们就可以很明显的看出,top本来应该贴在item的下方显示,但现在我们修改成了往下360的地方出现。


(2)final int bottom = top + mDivider.getIntrinsicHeight() + 50;


分割线的宽度是根据top加上一个固定值来决定的,也就是bottom的值,现在我们+50,也就是它的宽度增加了50,所以我们可以从最底部看到分割线增加了50,而上面的只是因为被藏在了后面,我们看不到而已。同样我们可以放大的来看。

final int bottom = top + mDivider.getIntrinsicHeight() + 200;
outRect.set(50, 0, 0, mDivider.getIntrinsicHeight());


同样的我们将childView右移,然后把分割线+200,我们就可以看到,item的后面其实分割线大到已经有重叠了(深灰色部分)。

所以其实最后我想说的是,在这里分割线的出现,其实是通过调整item里的childView以腾出空间来将我们本来已经画好的分割线显示出来,它就是一个覆盖的关系,item覆盖在了分割线的上方,我们要让分割线显示出来,就要去调整getItemOffsets()。











参考与扩展:

深入理解 RecyclerView 系列之一:ItemDecoration

Android RecyclerView 使用完全解析 体验艺术般的控件

0 0
原创粉丝点击