1. 说明
前边两节课我们已经写了ListView和GridView样式的分割线的具体实现,那么这节课我们就从RecyclerView的源码角度来分析下 - 分割线。
2. 源码分析
2.1 猜想1:
RecyclerView既然考虑了分割线,那么子View在测量的时候肯定要去考虑分割线留出的位置,直接看RecyclerView源码中的 measureChild()方法,源码方法如下:
/**
* Measure a child view using standard measurement policy, taking the padding
* of the parent RecyclerView and any added item decorations into account.
*
* <p>If the RecyclerView can be scrolled in either dimension the caller may
* pass 0 as the widthUsed or heightUsed parameters as they will be irrelevant.</p>
*
* @param child Child view to measure
* @param widthUsed Width in pixels currently consumed by other views, if relevant
* @param heightUsed Height in pixels currently consumed by other views, if relevant
*/
public void measureChild(View child, int widthUsed, int heightUsed) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
// 这个是最主要的方法 返回的是分割线所要考虑的Rect,这个Rect就相当于是个矩形,其实就是回调的getItemOffsets(),可以返回top、bottom、left、right ,所以在自定义的时候可以覆盖getItemOffsets()这个方法
final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child);
// 测量的时候要考虑的分割线距离
widthUsed += insets.left + insets.right;
heightUsed += insets.top + insets.bottom;
final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(),
getPaddingLeft() + getPaddingRight() + widthUsed, lp.width,
canScrollHorizontally());
final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(),
getPaddingTop() + getPaddingBottom() + heightUsed, lp.height,
canScrollVertically());
if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) {
child.measure(widthSpec, heightSpec);
}
}
2.2 猜想2:分割线会调用绘制的方法onDraw()
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
// 这个地方会回调分割线的onDraw()方法,所以你在自定义的那两个分割线的类中的onDraw()方法中想怎样绘制就怎样绘制,它都会回调回来的
mItemDecorations.get(i).onDraw(c, this, mState);
}
}