转载请注明出处:
http://write.blog.csdn.net/postedit/78753985
本文出自:【男儿当自强】
RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。
据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。
那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。
鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码:
mRecyclerView = findView(R.id.id_recyclerview);
//设置布局管理器
mRecyclerView.setLayoutManager(layout);
//设置adapter
mRecyclerView.setAdapter(adapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(
getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
RecycleView 默认情况使用系统默认的添加分割线类(DividerItemDecoration) 添加分割线,是在每个item下面添加一个分割线。在某些时候,我们是不希望每个item下面都添加一个分割线,比如第一个View作为RecycleView 的HeaderView的时候,我们不希望HeaderView有任何分割线。最后一个Item也不希望出现分割线(实际上看起来也很不爽)
我们查看系统默认的添加分割线的类(DividerItemDecoration)关键代码如下:
private void drawVertical(Canvas canvas, RecyclerView parent) {
canvas.save();
final int left;
final int right;
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
canvas.restore();
}
通过日志调试可以知道 parent.getChildCount()方法得到的是,当前屏幕内的子视图的数量。
那么我们不希望屏幕最后一个Item不出现分割线,那么我们可以让他少画一个就可以了(少执行一个for循环即可)
private void drawVertical(Canvas canvas, RecyclerView parent) {
canvas.save();
final int left;
final int right;
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount - 1; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
canvas.restore();
}
那么如果去掉第一个Item下面的分割线呢?(看官请慢慢往下看)
思路:我要找到第一个子View所在的Position,判断这个位置是不是0即可(position ==0), 如果是这个位置,就跳过,不让它画线
通过查看RecyclerView源码方法。我找到一个方法 getChildLayoutPosition,看到方法名字可以猜测这个方法是获取子视图所在的位置position,通过日志测试可以知道,确实是我们想要的方法,那么我们就可以通过这个方法得到我们想要的位置了,具体代码如下:
int pos = parent.getChildLayoutPosition(parent.getChildAt(i));
到这儿问题就可以解决了。下面贴上修改完后完整的代码:
private void drawVertical(Canvas canvas, RecyclerView parent) {
canvas.save();
final int left;
final int right;
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount - 1; i++) {
// 获取当前子试图所在的位置
int pos = parent.getChildLayoutPosition(parent.getChildAt(i));
// 跳过这个item不画线
if(i == 0 && pos == 0){
continue;
}
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
canvas.restore();
}