RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)

今天对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();		
		
	}
	
	@Override
	public void onDraw(Canvas c, RecyclerView parent, State state) {
		// TODO Auto-generated method stub
		super.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);
		}
	}
	
	@Override
	public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
		// TODO Auto-generated method stub
		super.getItemOffsets(outRect, view, parent, state);
		outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
	}
}


图:

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第1张图片




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

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

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

只修改getItemOffsets()

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第2张图片

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

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第3张图片

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

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第4张图片

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第5张图片

先不管分割线,因为我们的分割线是设置固定在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;

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第6张图片

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

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

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第7张图片

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


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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第8张图片

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

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

RecyclerView分割线之RecyclerView.ItemDecoration的理解(笔记)_第9张图片

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

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











参考与扩展:

深入理解 RecyclerView 系列之一:ItemDecoration

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

你可能感兴趣的:(Android学习笔记)