RecyclerView 添加分割线

在平时开发中,一直没有用到 Android提供的ItemDecoration来设置分割线,不太熟悉用法,基本都是写在列表的ViewHolder里,后来翻了一下Google提供的这个ItemDecoration,感觉还是挺好用的,花点时间,记录一下使用方法。

使用到ItemDecoration,基本步骤

1.编写一个RecyclerView.ItemDecoration的子类,
2.重写getItemOffsets方法 和onDraw方法。
3.为RecyclerView添加一个ItemDecoration。
其中重点是第二条重写getItemOffsets和onDraw方法。

1.先来看getItemOffsets方法

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}

先简单理解这个方法在itemview 上下左右偏移出多少的空间用来画分割线,等下看到具体效果就能明白。
这个偏移量怎么设置呢,就设置在第一个参数outRect里:
outRect.set(int left,int top,int right,int bottom);
这四个参数,分别代表了itmeview的 左,上,右,下的偏移量。
好了,这个时候推想一下,一个垂直方向的RecyclerView如果想在每个itemView的底部添加一个分割线,是不是就可以利用getItemOffsets方法,在itemView的底部偏移出一个空间来画分割线?
想法有了,可以试试,先在底部偏移出30px的空间。
先写一个RecyclerView ,代码如下

public class RecyClerViewLineActivity extends BaseActivity {
private RecyclerView mRecyclerView;
private NameAdapter mNameAdapter;
private LinearLayoutManager mLinearLayoutManager;
@Override
protected void initView() {
setContentView(R.layout.ac_recy);
mRecyclerView = (RecyclerView) findViewById(R.id.ac_recy_list_rcy);
mLinearLayoutManager = new LinearLayoutManager(this  );
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mNameAdapter = new NameAdapter(this);
mRecyclerView.setAdapter(mNameAdapter);
CustomItemDecoration  mItemDecoration=new CustomItemDecoration(this);
mRecyclerView.addItemDecoration(mItemDecoration);
}
}
public class CustomItemDecoration extends RecyclerView.ItemDecoration {
//利用系统属性中的listDivider来添加
public static final int[] ATRRS = new int[]{
android.R.attr.listDivider
};
private Context mContext;
private Drawable mDivder;
public CustomItemDecoration(Context mContext) {
this.mContext = mContext;
final TypedArray ta = mContext.obtainStyledAttributes(ATRRS);
this.mDivder = ta.getDrawable(0);
ta.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//只在下面 偏移
outRect.set(0, 0, 0,30);
}
}

简单的一个RecyclerView,每个itemView 有个TextView.

没有分割线的运行效果
底部偏移了30px的效果

比对后发现每个itemView底部多出了30px的空间 ,推测出来应该是修改的外边距,所以些分割线的时候,一定要算出精准的距离,否则会影响到写好的Ui效果。
另外可以测试一下 ,左右上下都修改的效果。

outRect.set(10,5,15,30);
修改的偏移量为10,5,15,30的效果

2.知道了getItemOffsets方法后,看现在看一下onDraw方法

 @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state); 

    }

后面两个参数先不看,只看第一个,很明显是传入一个画布,需要我们来画图了。
接着刚才的需求,我们已经在itemView的下方偏移出了一个30px的高度,需要画一个20px的高度的分割线。
要画图,得有画布和坐标,画布是给我们了,坐标需要我们算出来。
结合需求,发现
1)分割线的left 是一定的,都等于容器的paddingleft。
2)分割线的right也是一定的,都等于容器的width- 容器的paddingRigth。
只剩下top和bottom了。
3)top等于每个itemView的bottom+ 每个itemView的marginBottom(因为是在底部)
4)bottom等于 刚刚算出来的top+分割线自身的高度。
好了 ,四个左边都给了可以画图了。

@Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        //垂直的列表的分割线 ,左边距是一样的,这里减去 父容器才paddingLeft
        int left=parent.getPaddingLeft();
        //同样,右边也是一样的
        int right=parent.getWidth()-parent.getPaddingRight();
        //获取child的count
        int count=parent.getChildCount();
        //循环 获得 top  和 bottom
        for(int i=0;i<count;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams lyp =(RecyclerView.LayoutParams)child.getLayoutParams();
            // 获取 child 的底边到父容器的距离,因为分割线在itme的下面,所以这个距离就变成了分割线的距离父容器的 top
            int top=child.getBottom()+lyp.bottomMargin;
            //top再加分割线的高度,等于bottom
            int bottom=top+ 20;  //这里个20是假设的
            mDivder.setBounds(left,top,right,bottom);
            mDivder.draw(c);
        }


    }

看效果

30px的偏移和20px的分割线

好到此,垂直方向的分割线已经完成了。

3.其实根据刚才的推测,横向的RecyclerView的分割线原理也很好推测。(还是以右边偏移30px,分割线20px为列)

1)首先是偏移方向,需要再itemView的右边 偏移个30px的空间。
2)分割线的top 是一定的,都等于容器的paddingTop。
3)分割线的bottom也是一定的,都等于容器的height- 容器的paddingBottom。
只剩下right和left了。
4)left等于每个itemView的right+ 每个itemView的marginRight(因为是在右边)
5)right等于 刚刚算出来的left+分割线自身的宽度。

 @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

            //只在右边 偏移
            outRect.set(0, 0, 30,0);

    }

//在onDraw里调用
 private void drawHorizontal(Canvas c, RecyclerView parent) {
        //水平的列表的分割线 ,top是一定的
        int top=parent.getPaddingTop();
        //同样,bottom也是一定的
        int bottom=parent.getHeight()-parent.getPaddingBottom();

        //获取child的count
        int count=parent.getChildCount();
        //循环 获得 left  和 right
        for(int i=0;i<count;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams lyp =(RecyclerView.LayoutParams)child.getLayoutParams();
            // 获取 child 的右边到父容器的距离,因为分割线在itme的右边,所以这个距离就变成了分割线的距离父容器的 left
            int left=child.getRight()+lyp.rightMargin;
            //left再加分割线的宽度,等于right
            int right=left+ 20px;
            mDivder.setBounds(left,top,right,bottom);
            mDivder.draw(c);
        }



    }

效果

横向偏移30分割线20

以上就是在横向和纵向RecyclerView中添加分割线的做法,还可以写一个标识符,将纵向和横向分割符封装在同一个 ItemDecoration中,根据传入的不同值,来显示不同的效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容