recyclerview 分割线(去掉头和尾部)


转载请注明出处:
http://write.blog.csdn.net/postedit/78753985
本文出自:【男儿当自强】



概述

RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 
据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。

那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

  • 你想要控制其显示的方式,请通过布局管理器LayoutManager
  • 你想要控制Item间的间隔(可绘制),请通过ItemDecoration
  • 你想要控制Item增删的动画,请通过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();
    }



上面标红的代码是为每个item画一条分割线。我们就可以在这个方法 里面做文章了

通过日志调试可以知道  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

那么如果去掉第一个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();
    }


这样的话, 你可以控制去掉任何一个ItemView下面的分割线了











©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页