RecyclerView设置分隔线的三种方法

一、最简单的方法(布局划线)

在item.xml文件中在最下方指定一条分割线,例如:


       
       
  1. <?xml version=“1.0” encoding=“utf-8”?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:orientation= “vertical” android:layout_width= “match_parent”
  4. android:layout_height= “wrap_content”>
  5. <LinearLayout
  6. android:orientation= “horizontal”
  7. android:layout_width= “match_parent”
  8. android:layout_height= “wrap_content”>
  9. <ImageView
  10. android:id= “@+id/image_view”
  11. android:layout_gravity= “center”
  12. android:layout_width= “wrap_content”
  13. android:layout_height= “wrap_content” />
  14. <TextView
  15. android:id= “@+id/text_view”
  16. android:layout_gravity= “center”
  17. android:gravity= “left”
  18. android:layout_marginTop= “10dp”
  19. android:layout_width= “wrap_content”
  20. android:layout_height= “wrap_content” />
  21. </LinearLayout>
  22. <View
  23. android:layout_width= “match_parent”
  24. android:layout_height= “1dp”
  25. android:layout_marginTop= “10dp”
  26. android:background= “@color/colorPrimary”/>
  27. </LinearLayout>


————————————————————————————————————————————————————————

二、可以指定宽度颜色的模板(成品模板)


使用方法:

添加默认分割线:高度为2px,颜色为灰色

mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.VERTICAL));
       
       
  • 1
  • 1

添加自定义分割线:可自定义分割线drawable


       
       
  1. mRecyclerView .addItemDecoration( new RecycleViewDivider(
  2. mContext, LinearLayoutManager .VERTICAL, R .drawable .divider _mileage)) ;
  • 1
  • 2
  • 1
  • 2

添加自定义分割线:可自定义分割线高度和颜色


       
       
  1. mRecyclerView .addItemDecoration( new RecycleViewDivider(
  2. mContext, LinearLayoutManager .VERTICAL, 10, getResources() .getColor( R .color .divide _gray_color))) ;
  • 1
  • 2
  • 1
  • 2

万能分割线登场:


       
       
  1. public class RecycleViewDivider extends RecyclerView.ItemDecoration {
  2. private Paint mPaint;
  3. private Drawable mDivider;
  4. private int mDividerHeight = 2; //分割线高度,默认为1px
  5. private int mOrientation; //列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
  6. private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
  7. /**
  8. * 默认分割线:高度为2px,颜色为灰色
  9. *
  10. * @param context
  11. * @param orientation 列表方向
  12. */
  13. public RecycleViewDivider (Context context, int orientation) {
  14. if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
  15. throw new IllegalArgumentException( "请输入正确的参数!");
  16. }
  17. mOrientation = orientation;
  18. final TypedArray a = context.obtainStyledAttributes(ATTRS);
  19. mDivider = a.getDrawable( 0);
  20. a.recycle();
  21. }
  22. /**
  23. * 自定义分割线
  24. *
  25. * @param context
  26. * @param orientation 列表方向
  27. * @param drawableId 分割线图片
  28. */
  29. public RecycleViewDivider (Context context, int orientation, int drawableId) {
  30. this(context, orientation);
  31. mDivider = ContextCompat.getDrawable(context, drawableId);
  32. mDividerHeight = mDivider.getIntrinsicHeight();
  33. }
  34. /**
  35. * 自定义分割线
  36. *
  37. * @param context
  38. * @param orientation 列表方向
  39. * @param dividerHeight 分割线高度
  40. * @param dividerColor 分割线颜色
  41. */
  42. public RecycleViewDivider (Context context, int orientation, int dividerHeight, int dividerColor) {
  43. this(context, orientation);
  44. mDividerHeight = dividerHeight;
  45. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  46. mPaint.setColor(dividerColor);
  47. mPaint.setStyle(Paint.Style.FILL);
  48. }
  49. //获取分割线尺寸
  50. @Override
  51. public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  52. super.getItemOffsets(outRect, view, parent, state);
  53. outRect.set( 0, 0, 0, mDividerHeight);
  54. }
  55. //绘制分割线
  56. @Override
  57. public void onDraw (Canvas c, RecyclerView parent, RecyclerView.State state) {
  58. super.onDraw(c, parent, state);
  59. if (mOrientation == LinearLayoutManager.VERTICAL) {
  60. drawVertical(c, parent);
  61. } else {
  62. drawHorizontal(c, parent);
  63. }
  64. }
  65. //绘制横向 item 分割线
  66. private void drawHorizontal (Canvas canvas, RecyclerView parent) {
  67. final int left = parent.getPaddingLeft();
  68. final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
  69. final int childSize = parent.getChildCount();
  70. for ( int i = 0; i < childSize; i++) {
  71. final View child = parent.getChildAt(i);
  72. RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
  73. final int top = child.getBottom() + layoutParams.bottomMargin;
  74. final int bottom = top + mDividerHeight;
  75. if (mDivider != null) {
  76. mDivider.setBounds(left, top, right, bottom);
  77. mDivider.draw(canvas);
  78. }
  79. if (mPaint != null) {
  80. canvas.drawRect(left, top, right, bottom, mPaint);
  81. }
  82. }
  83. }
  84. //绘制纵向 item 分割线
  85. private void drawVertical (Canvas canvas, RecyclerView parent) {
  86. final int top = parent.getPaddingTop();
  87. final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
  88. final int childSize = parent.getChildCount();
  89. for ( int i = 0; i < childSize; i++) {
  90. final View child = parent.getChildAt(i);
  91. RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
  92. final int left = child.getRight() + layoutParams.rightMargin;
  93. final int right = left + mDividerHeight;
  94. if (mDivider != null) {
  95. mDivider.setBounds(left, top, right, bottom);
  96. mDivider.draw(canvas);
  97. }
  98. if (mPaint != null) {
  99. canvas.drawRect(left, top, right, bottom, mPaint);
  100. }
  101. }
  102. }
  103. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

附:自定的drawable文件一份


       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape = "rectangle" >
  4. <size android:height="20dp" />
  5. <solid android:color="#ff992900" />
  6. </shape>
原文:http://blog.csdn.net/pengkv/article/details/50538121

————————————————————————————————————————————————————————

三、用xml的详细内容介绍(有详细注释)


就在昨天中午,我在简书上发布了我个人的第一篇技术文档:RecyclerView系列之: RecyclerView系列之(1)为RecyclerView添加Header和Footer,也很有幸,能够得到那么多人的支持,这让我迫不及待的赶紧写第二篇文章。今天我将谈谈:为RecyclerView添加分隔线。


一. 理解ListView和RecyclerView中的ChildView

在讲为Item加入分割线本质的前,先来介绍,认识一下ChildView,也就是平时我们用到的ListView,RecyclerView中的getChildAt(int position)这个返回的ChildView是哪一部分?到底是哪一部分呢?一开始的时候,我理解错了,但是经过下面两张图这么一比较,你就明白了:


Item布局layout_margin == 0

Item布局Layout_margin == 16dp

下面看代码的区别:
第一张图的代码, 也就是每一个list_item的布局文件(下同)如下:


       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
  3. android:layout_width= "match_parent"
  4. android:layout_height= "50dp">
  5. <TextView
  6. android:id= "@+id/list_item"
  7. android:layout_width= "match_parent"
  8. android:layout_height= "match_parent"
  9. android:gravity= "center"
  10. android:textSize= "20sp"
  11. android:textColor= "#262526"
  12. android:background= "#08da1d"/>
  13. </LinearLayout>

第二张图的代码:


       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
  3. android:layout_width= "match_parent"
  4. android:layout_height= "50dp"
  5. android:layout_margin= "16dp">
  6. <TextView
  7. android:id= "@+id/list_item"
  8. android:layout_width= "match_parent"
  9. android:layout_height= "match_parent"
  10. android:gravity= "center"
  11. android:textSize= "20sp"
  12. android:textColor= "#262526"
  13. android:background= "#08da1d"/>
  14. </LinearLayout>

仔细看一下,它们的不同之处, 就是第二个图的代码中多了:

android:layout_margin = "16dp"
       
       

就多这一句而已。

所以到这里我们应该知道了ChildView是哪一部分了,就是图二中绿色这一部分,边距这一部分并不属于ChildView, 而是属于ChildView的布局。

这样我们了解ChildView之后,下面再来理解加入分隔线的原理就简单多了。

二. 理解加入分隔线的原理

在ListView中,Google为我们提供了SetDivider(Drawable divider)这样的方法来设置分隔线,那么在RecyclerView中,Google又为我们提供了什么样的方法去添加分隔线呢?通过查看官方文档,它,提供了:addItemDecoration(RecyclerView.ItemDecoration decor)这个方法了设置分隔线,那问题又来了,RecyclerView.ItemDecoration是什么东西呢?继续查:然后发现如下:它原来是一个类,里面封装了三个方法:
(1)void getItemOffsets ()
(2)void onDraw ()
(3)void onDrawOver ()


通过上面的三个方法,可以看出,这是要自己直接画上去,准确的说这几个方法是:添加Divider,主要是找到添加Divider的位置, 而Divider是在drawable文件中写好了的。 利用onDraw和onDrawOver都差不多,我们在创建自己的Decoration类继承RecyclerView.ItemDecoration的时候,我们只要重写getItemOffsets(),还有onDraw()和onDrawOver两者其中之一就可以了.



那getItemOffsets()方法有什么用呢?从字面意思就是Item要偏移, 由于我们在Item和Item之间加入了分隔线,线其实本质就是一个长方形,也是用户自定义的,既然线也有长宽高,就画横线来说,上面的Item加入了分隔线,那下面的Item就要往下平移,平移的量就是分隔线的高度。不理解每关系,后面看代码就容易理解了。



现在我们知道了如何添加了,就是通过画,那到底是画在哪里呢?画的位置又怎么确定呢?下面看图:


分隔线的位置图

我现在拿画横线来说,从上面这个图中,我们很容易就可以看到,我们画分隔线的位置,是在每一个Item的布局之间,注意:是布局之间。

好了,我们确定了画在哪里,那我们怎么确定画线的具体的坐标位置呢?也就是我们要确定:分隔线的left, top, right, Bottom. 在Adapter中,我们很容易通过parent(这个parent它其实就是我们能看到的部分)获取每一个childView:
(1)left:parent.getPaddingLeft()
(2)right: parent. getWidth()-parent.getPaddingRight();
(3)top : 就是红线的上面:我们通过ChildView.getBottom()来得到这个Item的底部的高度,也就是蓝线位置,蓝线和红线之间间距:就是这个Item布局文件的:layout_marginBottom, 然后top的位置就是两者之和。
(4)bttom: 就是top加上分隔线的高度:top+线高


通过上面的解析,你也许知道了加入分隔线的原理,不理解也没有关系,说也不是说得很清楚,下面直接上代码,通过代码来理解。

三. Talk is cheap, show you the code.

(1)首先,先来看主布局文件:activity_main.xml:

       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.design.widget.CoordinatorLayout
  3. xmlns:android= "http://schemas.android.com/apk/res/android"
  4. xmlns:tools= "http://schemas.android.com/tools"
  5. android:layout_width= "match_parent"
  6. android:layout_height= "match_parent"
  7. android:fitsSystemWindows= "true"
  8. tools:context= "com.study.wnw.recyclerviewdivider.MainActivity">
  9. <android.support.v7.widget.RecyclerView
  10. android:id= "@+id/recyclerview"
  11. android:layout_width= "match_parent"
  12. android:layout_height= "match_parent">
  13. </android.support.v7.widget.RecyclerView>
  14. </android.support.design.widget.CoordinatorLayout>

我在这里面仅仅加入了一个RecyclerView


(2)RecyclerView里面每个Item的布局文件:item_view.xml


       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation= "vertical"
  4. android:layout_width= "match_parent"
  5. android:layout_height= "50dp"
  6. android:layout_margin= "16sp">
  7. <TextView
  8. android:id= "@+id/list_item"
  9. android:layout_width= "match_parent"
  10. android:layout_height= "match_parent"
  11. android:gravity= "center"
  12. android:textSize= "20sp"
  13. android:textColor= "#f7f4f7"
  14. android:background= "#08da1d"/>
  15. </LinearLayout>

这也没有什么可讲的,就是在里面添加一个TextView用来显示文本


(3)我们RecyclerView的适配器MyAdapater.java:


       
       
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.content.Context;
  3. import android.support.v7.widget.RecyclerView;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.TextView;
  8. import java.util.List;
  9. import java.util.concurrent.CopyOnWriteArrayList;
  10. /** * Created by wnw on 16-5-22. */
  11. public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  12. //定义一个集合,接收从Activity中传递过来的数据和上下文
  13. private List<String> mList;
  14. private Context mContext;
  15. MyAdapter(Context context, List<String> list){
  16. this.mContext = context;
  17. this.mList = list;
  18. }
  19. //得到child的数量
  20. @Override
  21. public int getItemCount() {
  22. return mList.size();
  23. }
  24. //创建ChildView
  25. @Override
  26. public RecyclerView. ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  27. View layout = LayoutInflater.from(mContext).inflate(R.layout.item_view, parent, false);
  28. return new MyHolder(layout);
  29. }
  30. //将数据绑定到每一个childView中
  31. @Override
  32. public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  33. if (holder instanceof MyHolder){
  34. final String itemText = mList.get(position);
  35. ((MyHolder)holder).tv.setText(itemText);
  36. }
  37. }
  38. // 通过holder的方式来初始化每一个ChildView的内容
  39. class MyHolder extends RecyclerView.ViewHolder{
  40. TextView tv;
  41. public MyHolder(View itemView) {
  42. super(itemView);
  43. tv = (TextView)itemView.findViewById(R.id.list_item);
  44. }
  45. }
  46. }

好了,这里也没有什么好讲的,也不是我们这篇文章的重点,下面重点来了。


(4)我们自定义的MyDecoration.java:(继承RecyclerView.ItemDecoration)


       
       
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.Canvas;
  5. import android.graphics.Rect;
  6. import android.graphics.drawable.Drawable;
  7. import android.support.v7.widget.LinearLayoutManager;
  8. import android.support.v7.widget.RecyclerView;
  9. import android.util.Log;
  10. import android.view.View;
  11. /** * Created by wnw on 16-5-22. */
  12. public class MyDecoration extends RecyclerView.ItemDecoration{
  13. private Context mContext;
  14. private Drawable mDivider;
  15. private int mOrientation;
  16. public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
  17. public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
  18. //我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置
  19. public static final int[] ATRRS = new int[]{
  20. android.R.attr.listDivider //在style.xml文件的AppTheme主题中中设定<item name="android:listDivider">@drawable/divider</item> ---- 见下文
  21. };
  22. public MyDecoration(Context context, int orientation) {
  23. this.mContext = context;
  24. final TypedArray ta = context.obtainStyledAttributes(ATRRS);
  25. this.mDivider = ta.getDrawable(0);
  26. ta.recycle();
  27. setOrientation(orientation);
  28. }
  29. //设置屏幕的方向
  30. public void setOrientation(int orientation){
  31. if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
  32. throw new IllegalArgumentException( "invalid orientation"); } mOrientation = orientation;
  33. }
  34. @Override
  35. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  36. if (mOrientation == HORIZONTAL_LIST){
  37. drawVerticalLine(c, parent, state);
  38. } else {
  39. drawHorizontalLine(c, parent, state);
  40. }
  41. }
  42. //画横线, 这里的parent其实是显示在屏幕显示的这部分
  43. public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
  44. int left = parent.getPaddingLeft(); //横线的左端必须是paddngleft,如果用left则横线过长(不显示)
  45. int right = parent.getWidth() - parent.getPaddingRight(); //同上,getLeft()是控件左端距离屏幕左端的长度,right是控件右端距离屏幕左端的长度
  46. final int childCount = parent.getChildCount(); //接上:getwidth是控件的宽度(如不在view中的onDraw()使用measure方法测量,getMeasuredWidth同)
  47. for ( int i = 0; i < childCount; i++){
  48. final View child = parent.getChildAt(i);
  49. //获得child的布局信息(主要是获取 LayoutParams中的params.bottomMargin长度
  50. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
  51. final int top = child.getBottom() + params.bottomMargin;
  52. final int bottom = top + mDivider.getIntrinsicHeight(); //getIntrinsicHeight()方法是返回drawable文件固有的高度,以dp为单位
  53. mDivider.setBounds(left, top, right, bottom); //setBounds()方法主要是设定分割线控件的长宽
  54. mDivider.draw(c);
  55. //Log.d("wnw", left + " " + top + " "+right+" "+bottom+" "+i);
  56. }
  57. }
  58. //画竖线
  59. public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
  60. int top = parent.getPaddingTop();
  61. int bottom = parent.getHeight() - parent.getPaddingBottom();
  62. final int childCount = parent.getChildCount();
  63. for ( int i = 0; i < childCount; i++){
  64. final View child = parent.getChildAt(i);
  65. //获得child的布局信息
  66. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
  67. final int left = child.getRight() + params.rightMargin;
  68. final int right = left + mDivider.getIntrinsicWidth();
  69. mDivider.setBounds(left, top, right, bottom);
  70. mDivider.draw(c);
  71. }
  72. }
  73. //由于Divider也有长宽高,每一个Item需要向下或者向右偏移
  74. @Override
  75. public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  76. if(mOrientation == HORIZONTAL_LIST){
  77. //画横线,就是往下偏移一个分割线的高度
  78. outRect.set( 0, 0, 0, mDivider.getIntrinsicHeight());
  79. } else {
  80. //画竖线,就是往右偏移一个分割线的宽度
  81. outRect.set( 0, 0, mDivider.getIntrinsicWidth(), 0);
  82. }
  83. }
  84. }

从上面的代码中,我们还通过系统属性来适应屏幕的横屏和竖屏,然后确定画横的,还是竖的Divider,其实在里面我们做了三件事,第一件是:获取到系统中的listDivider, 我们就是通过它在主题中去设置的,下面第(6)小点看一下代码就知道了。第二件事:就是找到我们需要添加Divider的位置,从onDraw方法中去找到,并将Divider添加进去。第三个是:得到Item的偏移量。


(5)看看我们的MainActivity.java


       
       
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.support.v7.widget.LinearLayoutManager;
  5. import android.support.v7.widget.RecyclerView;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. public class MainActivity extends AppCompatActivity {
  9. //定义RecyclerView
  10. private RecyclerView mRecyclerView = null;
  11. //定义一个List集合,用于存放RecyclerView中的每一个数据
  12. private List<String> mData = null;
  13. //定义一个Adapter
  14. private MyAdapter mAdapter;
  15. //定义一个LinearLayoutManager
  16. private LinearLayoutManager mLayoutManager;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_main);
  21. //RecyclerView三步曲+LayoutManager
  22. initView();
  23. initData();
  24. mAdapter = new MyAdapter( this,mData);
  25. mRecyclerView.setLayoutManager(mLayoutManager);
  26. mRecyclerView.setAdapter(mAdapter);
  27. //这句就是添加我们自定义的分隔线
  28. mRecyclerView.addItemDecoration( new MyDecoration( this, MyDecoration.VERTICAL_LIST));
  29. }
  30. //初始化View
  31. private void initView(){
  32. mLayoutManager = new LinearLayoutManager( this);
  33. mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
  34. }
  35. //初始化加载到RecyclerView中的数据, 我这里只是给每一个Item添加了String类型的数据
  36. private void initData(){
  37. mData = new ArrayList<String>();
  38. for ( int i = 0; i < 20; i++){
  39. mData.add( "Item" + i);
  40. }
  41. }
  42. }
(6)分隔线Divider的drawable文件:divider.xml

       
       
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape= "rectangle">
  4. <solid android:color="#7b7a7a"/>
  5. <size android:height="1dp"/>
  6. </shape>

我们在这里面,画了一个:rectangle, 给它填充颜色,还有高度,这样就搞定了,高度小,显示出来也是一条线:其实线的本质就是长方形。这里可以根据个人需要,画不同类型的divider


(7)在styles.xml的AppTheme中,设置listDivider为我们的divider.xml文件:


       
       
  1. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  2. <item name="android:listDivider">@drawable/divider </item>
  3. </style>

这样,我们将系统的listDivider设置成我们自定义的divider. 还记得我们在MyDecoration中获取系统的listDivider这个属性吗,这样通过这个属性,我们就可以将我们的divider.xml文件和MyDecoration.java进行关联了。


到这里所有的工作就完成了,下面展示一下运行结果:


竖屏效果图

横屏效果图


经过几个小时的写作,终于搞定了,虽然仅仅是一个添加分隔线的功能,但是还是想尽可能的通过自己的语言去理解,去认知它的原理,这样做起来就简单多了。一开始的时候,我夜不知道怎么去用,也参考了别人写的文章,特别是鸿洋大神的:Android RecyclerView 使用完全解析 体验艺术般的控件, 写得特别的棒,从中也学到了一些知识。



好了,这篇文章暂时写到这里了,简单的介绍了一些RecyclerView分隔线的原理和添加方法,希望大家能够多多交流,过几天我会继续写下一篇文章,RecyclerView系列之(3):为RecyclerView添加下拉刷新和上拉加载的功能。最后还是要感谢大家,感谢这个平台,能够让我们一起交流,一切学习。





作者:右眼皮的爱
链接: http://www.jianshu.com/p/4eff036360da
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


转自: https://blog.csdn.net/yancychas/article/details/77484659

一、最简单的方法(布局划线)

在item.xml文件中在最下方指定一条分割线,例如:


     
     
  1. <?xml version=“1.0” encoding=“utf-8”?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:orientation= “vertical” android:layout_width= “match_parent”
  4. android:layout_height= “wrap_content”>
  5. <LinearLayout
  6. android:orientation= “horizontal”
  7. android:layout_width= “match_parent”
  8. android:layout_height= “wrap_content”>
  9. <ImageView
  10. android:id= “@+id/image_view”
  11. android:layout_gravity= “center”
  12. android:layout_width= “wrap_content”
  13. android:layout_height= “wrap_content” />
  14. <TextView
  15. android:id= “@+id/text_view”
  16. android:layout_gravity= “center”
  17. android:gravity= “left”
  18. android:layout_marginTop= “10dp”
  19. android:layout_width= “wrap_content”
  20. android:layout_height= “wrap_content” />
  21. </LinearLayout>
  22. <View
  23. android:layout_width= “match_parent”
  24. android:layout_height= “1dp”
  25. android:layout_marginTop= “10dp”
  26. android:background= “@color/colorPrimary”/>
  27. </LinearLayout>


————————————————————————————————————————————————————————

二、可以指定宽度颜色的模板(成品模板)


使用方法:

添加默认分割线:高度为2px,颜色为灰色

mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.VERTICAL));
     
     
  • 1
  • 1

添加自定义分割线:可自定义分割线drawable


     
     
  1. mRecyclerView .addItemDecoration( new RecycleViewDivider(
  2. mContext, LinearLayoutManager .VERTICAL, R .drawable .divider _mileage)) ;
  • 1
  • 2
  • 1
  • 2

添加自定义分割线:可自定义分割线高度和颜色


     
     
  1. mRecyclerView .addItemDecoration( new RecycleViewDivider(
  2. mContext, LinearLayoutManager .VERTICAL, 10, getResources() .getColor( R .color .divide _gray_color))) ;
  • 1
  • 2
  • 1
  • 2

万能分割线登场:


     
     
  1. public class RecycleViewDivider extends RecyclerView.ItemDecoration {
  2. private Paint mPaint;
  3. private Drawable mDivider;
  4. private int mDividerHeight = 2; //分割线高度,默认为1px
  5. private int mOrientation; //列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
  6. private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
  7. /**
  8. * 默认分割线:高度为2px,颜色为灰色
  9. *
  10. * @param context
  11. * @param orientation 列表方向
  12. */
  13. public RecycleViewDivider (Context context, int orientation) {
  14. if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
  15. throw new IllegalArgumentException( "请输入正确的参数!");
  16. }
  17. mOrientation = orientation;
  18. final TypedArray a = context.obtainStyledAttributes(ATTRS);
  19. mDivider = a.getDrawable( 0);
  20. a.recycle();
  21. }
  22. /**
  23. * 自定义分割线
  24. *
  25. * @param context
  26. * @param orientation 列表方向
  27. * @param drawableId 分割线图片
  28. */
  29. public RecycleViewDivider (Context context, int orientation, int drawableId) {
  30. this(context, orientation);
  31. mDivider = ContextCompat.getDrawable(context, drawableId);
  32. mDividerHeight = mDivider.getIntrinsicHeight();
  33. }
  34. /**
  35. * 自定义分割线
  36. *
  37. * @param context
  38. * @param orientation 列表方向
  39. * @param dividerHeight 分割线高度
  40. * @param dividerColor 分割线颜色
  41. */
  42. public RecycleViewDivider (Context context, int orientation, int dividerHeight, int dividerColor) {
  43. this(context, orientation);
  44. mDividerHeight = dividerHeight;
  45. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  46. mPaint.setColor(dividerColor);
  47. mPaint.setStyle(Paint.Style.FILL);
  48. }
  49. //获取分割线尺寸
  50. @Override
  51. public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  52. super.getItemOffsets(outRect, view, parent, state);
  53. outRect.set( 0, 0, 0, mDividerHeight);
  54. }
  55. //绘制分割线
  56. @Override
  57. public void onDraw (Canvas c, RecyclerView parent, RecyclerView.State state) {
  58. super.onDraw(c, parent, state);
  59. if (mOrientation == LinearLayoutManager.VERTICAL) {
  60. drawVertical(c, parent);
  61. } else {
  62. drawHorizontal(c, parent);
  63. }
  64. }
  65. //绘制横向 item 分割线
  66. private void drawHorizontal (Canvas canvas, RecyclerView parent) {
  67. final int left = parent.getPaddingLeft();
  68. final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
  69. final int childSize = parent.getChildCount();
  70. for ( int i = 0; i < childSize; i++) {
  71. final View child = parent.getChildAt(i);
  72. RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
  73. final int top = child.getBottom() + layoutParams.bottomMargin;
  74. final int bottom = top + mDividerHeight;
  75. if (mDivider != null) {
  76. mDivider.setBounds(left, top, right, bottom);
  77. mDivider.draw(canvas);
  78. }
  79. if (mPaint != null) {
  80. canvas.drawRect(left, top, right, bottom, mPaint);
  81. }
  82. }
  83. }
  84. //绘制纵向 item 分割线
  85. private void drawVertical (Canvas canvas, RecyclerView parent) {
  86. final int top = parent.getPaddingTop();
  87. final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
  88. final int childSize = parent.getChildCount();
  89. for ( int i = 0; i < childSize; i++) {
  90. final View child = parent.getChildAt(i);
  91. RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
  92. final int left = child.getRight() + layoutParams.rightMargin;
  93. final int right = left + mDividerHeight;
  94. if (mDivider != null) {
  95. mDivider.setBounds(left, top, right, bottom);
  96. mDivider.draw(canvas);
  97. }
  98. if (mPaint != null) {
  99. canvas.drawRect(left, top, right, bottom, mPaint);
  100. }
  101. }
  102. }
  103. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

附:自定的drawable文件一份


     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape = "rectangle" >
  4. <size android:height="20dp" />
  5. <solid android:color="#ff992900" />
  6. </shape>
原文:http://blog.csdn.net/pengkv/article/details/50538121

————————————————————————————————————————————————————————

三、用xml的详细内容介绍(有详细注释)


就在昨天中午,我在简书上发布了我个人的第一篇技术文档:RecyclerView系列之: RecyclerView系列之(1)为RecyclerView添加Header和Footer,也很有幸,能够得到那么多人的支持,这让我迫不及待的赶紧写第二篇文章。今天我将谈谈:为RecyclerView添加分隔线。


一. 理解ListView和RecyclerView中的ChildView

在讲为Item加入分割线本质的前,先来介绍,认识一下ChildView,也就是平时我们用到的ListView,RecyclerView中的getChildAt(int position)这个返回的ChildView是哪一部分?到底是哪一部分呢?一开始的时候,我理解错了,但是经过下面两张图这么一比较,你就明白了:


Item布局layout_margin == 0

Item布局Layout_margin == 16dp

下面看代码的区别:
第一张图的代码, 也就是每一个list_item的布局文件(下同)如下:


     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
  3. android:layout_width= "match_parent"
  4. android:layout_height= "50dp">
  5. <TextView
  6. android:id= "@+id/list_item"
  7. android:layout_width= "match_parent"
  8. android:layout_height= "match_parent"
  9. android:gravity= "center"
  10. android:textSize= "20sp"
  11. android:textColor= "#262526"
  12. android:background= "#08da1d"/>
  13. </LinearLayout>

第二张图的代码:


     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
  3. android:layout_width= "match_parent"
  4. android:layout_height= "50dp"
  5. android:layout_margin= "16dp">
  6. <TextView
  7. android:id= "@+id/list_item"
  8. android:layout_width= "match_parent"
  9. android:layout_height= "match_parent"
  10. android:gravity= "center"
  11. android:textSize= "20sp"
  12. android:textColor= "#262526"
  13. android:background= "#08da1d"/>
  14. </LinearLayout>

仔细看一下,它们的不同之处, 就是第二个图的代码中多了:

android:layout_margin = "16dp"
     
     

就多这一句而已。

所以到这里我们应该知道了ChildView是哪一部分了,就是图二中绿色这一部分,边距这一部分并不属于ChildView, 而是属于ChildView的布局。

这样我们了解ChildView之后,下面再来理解加入分隔线的原理就简单多了。

二. 理解加入分隔线的原理

在ListView中,Google为我们提供了SetDivider(Drawable divider)这样的方法来设置分隔线,那么在RecyclerView中,Google又为我们提供了什么样的方法去添加分隔线呢?通过查看官方文档,它,提供了:addItemDecoration(RecyclerView.ItemDecoration decor)这个方法了设置分隔线,那问题又来了,RecyclerView.ItemDecoration是什么东西呢?继续查:然后发现如下:它原来是一个类,里面封装了三个方法:
(1)void getItemOffsets ()
(2)void onDraw ()
(3)void onDrawOver ()


通过上面的三个方法,可以看出,这是要自己直接画上去,准确的说这几个方法是:添加Divider,主要是找到添加Divider的位置, 而Divider是在drawable文件中写好了的。 利用onDraw和onDrawOver都差不多,我们在创建自己的Decoration类继承RecyclerView.ItemDecoration的时候,我们只要重写getItemOffsets(),还有onDraw()和onDrawOver两者其中之一就可以了.



那getItemOffsets()方法有什么用呢?从字面意思就是Item要偏移, 由于我们在Item和Item之间加入了分隔线,线其实本质就是一个长方形,也是用户自定义的,既然线也有长宽高,就画横线来说,上面的Item加入了分隔线,那下面的Item就要往下平移,平移的量就是分隔线的高度。不理解每关系,后面看代码就容易理解了。



现在我们知道了如何添加了,就是通过画,那到底是画在哪里呢?画的位置又怎么确定呢?下面看图:


分隔线的位置图

我现在拿画横线来说,从上面这个图中,我们很容易就可以看到,我们画分隔线的位置,是在每一个Item的布局之间,注意:是布局之间。

好了,我们确定了画在哪里,那我们怎么确定画线的具体的坐标位置呢?也就是我们要确定:分隔线的left, top, right, Bottom. 在Adapter中,我们很容易通过parent(这个parent它其实就是我们能看到的部分)获取每一个childView:
(1)left:parent.getPaddingLeft()
(2)right: parent. getWidth()-parent.getPaddingRight();
(3)top : 就是红线的上面:我们通过ChildView.getBottom()来得到这个Item的底部的高度,也就是蓝线位置,蓝线和红线之间间距:就是这个Item布局文件的:layout_marginBottom, 然后top的位置就是两者之和。
(4)bttom: 就是top加上分隔线的高度:top+线高


通过上面的解析,你也许知道了加入分隔线的原理,不理解也没有关系,说也不是说得很清楚,下面直接上代码,通过代码来理解。

三. Talk is cheap, show you the code.

(1)首先,先来看主布局文件:activity_main.xml:

     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.design.widget.CoordinatorLayout
  3. xmlns:android= "http://schemas.android.com/apk/res/android"
  4. xmlns:tools= "http://schemas.android.com/tools"
  5. android:layout_width= "match_parent"
  6. android:layout_height= "match_parent"
  7. android:fitsSystemWindows= "true"
  8. tools:context= "com.study.wnw.recyclerviewdivider.MainActivity">
  9. <android.support.v7.widget.RecyclerView
  10. android:id= "@+id/recyclerview"
  11. android:layout_width= "match_parent"
  12. android:layout_height= "match_parent">
  13. </android.support.v7.widget.RecyclerView>
  14. </android.support.design.widget.CoordinatorLayout>

我在这里面仅仅加入了一个RecyclerView


(2)RecyclerView里面每个Item的布局文件:item_view.xml


     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation= "vertical"
  4. android:layout_width= "match_parent"
  5. android:layout_height= "50dp"
  6. android:layout_margin= "16sp">
  7. <TextView
  8. android:id= "@+id/list_item"
  9. android:layout_width= "match_parent"
  10. android:layout_height= "match_parent"
  11. android:gravity= "center"
  12. android:textSize= "20sp"
  13. android:textColor= "#f7f4f7"
  14. android:background= "#08da1d"/>
  15. </LinearLayout>

这也没有什么可讲的,就是在里面添加一个TextView用来显示文本


(3)我们RecyclerView的适配器MyAdapater.java:


     
     
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.content.Context;
  3. import android.support.v7.widget.RecyclerView;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.TextView;
  8. import java.util.List;
  9. import java.util.concurrent.CopyOnWriteArrayList;
  10. /** * Created by wnw on 16-5-22. */
  11. public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  12. //定义一个集合,接收从Activity中传递过来的数据和上下文
  13. private List<String> mList;
  14. private Context mContext;
  15. MyAdapter(Context context, List<String> list){
  16. this.mContext = context;
  17. this.mList = list;
  18. }
  19. //得到child的数量
  20. @Override
  21. public int getItemCount() {
  22. return mList.size();
  23. }
  24. //创建ChildView
  25. @Override
  26. public RecyclerView. ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  27. View layout = LayoutInflater.from(mContext).inflate(R.layout.item_view, parent, false);
  28. return new MyHolder(layout);
  29. }
  30. //将数据绑定到每一个childView中
  31. @Override
  32. public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  33. if (holder instanceof MyHolder){
  34. final String itemText = mList.get(position);
  35. ((MyHolder)holder).tv.setText(itemText);
  36. }
  37. }
  38. // 通过holder的方式来初始化每一个ChildView的内容
  39. class MyHolder extends RecyclerView.ViewHolder{
  40. TextView tv;
  41. public MyHolder(View itemView) {
  42. super(itemView);
  43. tv = (TextView)itemView.findViewById(R.id.list_item);
  44. }
  45. }
  46. }

好了,这里也没有什么好讲的,也不是我们这篇文章的重点,下面重点来了。


(4)我们自定义的MyDecoration.java:(继承RecyclerView.ItemDecoration)


     
     
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.Canvas;
  5. import android.graphics.Rect;
  6. import android.graphics.drawable.Drawable;
  7. import android.support.v7.widget.LinearLayoutManager;
  8. import android.support.v7.widget.RecyclerView;
  9. import android.util.Log;
  10. import android.view.View;
  11. /** * Created by wnw on 16-5-22. */
  12. public class MyDecoration extends RecyclerView.ItemDecoration{
  13. private Context mContext;
  14. private Drawable mDivider;
  15. private int mOrientation;
  16. public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
  17. public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
  18. //我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置
  19. public static final int[] ATRRS = new int[]{
  20. android.R.attr.listDivider //在style.xml文件的AppTheme主题中中设定<item name="android:listDivider">@drawable/divider</item> ---- 见下文
  21. };
  22. public MyDecoration(Context context, int orientation) {
  23. this.mContext = context;
  24. final TypedArray ta = context.obtainStyledAttributes(ATRRS);
  25. this.mDivider = ta.getDrawable(0);
  26. ta.recycle();
  27. setOrientation(orientation);
  28. }
  29. //设置屏幕的方向
  30. public void setOrientation(int orientation){
  31. if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
  32. throw new IllegalArgumentException( "invalid orientation"); } mOrientation = orientation;
  33. }
  34. @Override
  35. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  36. if (mOrientation == HORIZONTAL_LIST){
  37. drawVerticalLine(c, parent, state);
  38. } else {
  39. drawHorizontalLine(c, parent, state);
  40. }
  41. }
  42. //画横线, 这里的parent其实是显示在屏幕显示的这部分
  43. public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
  44. int left = parent.getPaddingLeft(); //横线的左端必须是paddngleft,如果用left则横线过长(不显示)
  45. int right = parent.getWidth() - parent.getPaddingRight(); //同上,getLeft()是控件左端距离屏幕左端的长度,right是控件右端距离屏幕左端的长度
  46. final int childCount = parent.getChildCount(); //接上:getwidth是控件的宽度(如不在view中的onDraw()使用measure方法测量,getMeasuredWidth同)
  47. for ( int i = 0; i < childCount; i++){
  48. final View child = parent.getChildAt(i);
  49. //获得child的布局信息(主要是获取 LayoutParams中的params.bottomMargin长度
  50. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
  51. final int top = child.getBottom() + params.bottomMargin;
  52. final int bottom = top + mDivider.getIntrinsicHeight(); //getIntrinsicHeight()方法是返回drawable文件固有的高度,以dp为单位
  53. mDivider.setBounds(left, top, right, bottom); //setBounds()方法主要是设定分割线控件的长宽
  54. mDivider.draw(c);
  55. //Log.d("wnw", left + " " + top + " "+right+" "+bottom+" "+i);
  56. }
  57. }
  58. //画竖线
  59. public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
  60. int top = parent.getPaddingTop();
  61. int bottom = parent.getHeight() - parent.getPaddingBottom();
  62. final int childCount = parent.getChildCount();
  63. for ( int i = 0; i < childCount; i++){
  64. final View child = parent.getChildAt(i);
  65. //获得child的布局信息
  66. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
  67. final int left = child.getRight() + params.rightMargin;
  68. final int right = left + mDivider.getIntrinsicWidth();
  69. mDivider.setBounds(left, top, right, bottom);
  70. mDivider.draw(c);
  71. }
  72. }
  73. //由于Divider也有长宽高,每一个Item需要向下或者向右偏移
  74. @Override
  75. public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  76. if(mOrientation == HORIZONTAL_LIST){
  77. //画横线,就是往下偏移一个分割线的高度
  78. outRect.set( 0, 0, 0, mDivider.getIntrinsicHeight());
  79. } else {
  80. //画竖线,就是往右偏移一个分割线的宽度
  81. outRect.set( 0, 0, mDivider.getIntrinsicWidth(), 0);
  82. }
  83. }
  84. }

从上面的代码中,我们还通过系统属性来适应屏幕的横屏和竖屏,然后确定画横的,还是竖的Divider,其实在里面我们做了三件事,第一件是:获取到系统中的listDivider, 我们就是通过它在主题中去设置的,下面第(6)小点看一下代码就知道了。第二件事:就是找到我们需要添加Divider的位置,从onDraw方法中去找到,并将Divider添加进去。第三个是:得到Item的偏移量。


(5)看看我们的MainActivity.java


     
     
  1. package com.study.wnw.recyclerviewdivider;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.support.v7.widget.LinearLayoutManager;
  5. import android.support.v7.widget.RecyclerView;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. public class MainActivity extends AppCompatActivity {
  9. //定义RecyclerView
  10. private RecyclerView mRecyclerView = null;
  11. //定义一个List集合,用于存放RecyclerView中的每一个数据
  12. private List<String> mData = null;
  13. //定义一个Adapter
  14. private MyAdapter mAdapter;
  15. //定义一个LinearLayoutManager
  16. private LinearLayoutManager mLayoutManager;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_main);
  21. //RecyclerView三步曲+LayoutManager
  22. initView();
  23. initData();
  24. mAdapter = new MyAdapter( this,mData);
  25. mRecyclerView.setLayoutManager(mLayoutManager);
  26. mRecyclerView.setAdapter(mAdapter);
  27. //这句就是添加我们自定义的分隔线
  28. mRecyclerView.addItemDecoration( new MyDecoration( this, MyDecoration.VERTICAL_LIST));
  29. }
  30. //初始化View
  31. private void initView(){
  32. mLayoutManager = new LinearLayoutManager( this);
  33. mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
  34. }
  35. //初始化加载到RecyclerView中的数据, 我这里只是给每一个Item添加了String类型的数据
  36. private void initData(){
  37. mData = new ArrayList<String>();
  38. for ( int i = 0; i < 20; i++){
  39. mData.add( "Item" + i);
  40. }
  41. }
  42. }
(6)分隔线Divider的drawable文件:divider.xml

     
     
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape= "rectangle">
  4. <solid android:color="#7b7a7a"/>
  5. <size android:height="1dp"/>
  6. </shape>

我们在这里面,画了一个:rectangle, 给它填充颜色,还有高度,这样就搞定了,高度小,显示出来也是一条线:其实线的本质就是长方形。这里可以根据个人需要,画不同类型的divider


(7)在styles.xml的AppTheme中,设置listDivider为我们的divider.xml文件:


     
     
  1. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  2. <item name="android:listDivider">@drawable/divider </item>
  3. </style>

这样,我们将系统的listDivider设置成我们自定义的divider. 还记得我们在MyDecoration中获取系统的listDivider这个属性吗,这样通过这个属性,我们就可以将我们的divider.xml文件和MyDecoration.java进行关联了。


到这里所有的工作就完成了,下面展示一下运行结果:


竖屏效果图

横屏效果图


经过几个小时的写作,终于搞定了,虽然仅仅是一个添加分隔线的功能,但是还是想尽可能的通过自己的语言去理解,去认知它的原理,这样做起来就简单多了。一开始的时候,我夜不知道怎么去用,也参考了别人写的文章,特别是鸿洋大神的:Android RecyclerView 使用完全解析 体验艺术般的控件, 写得特别的棒,从中也学到了一些知识。



好了,这篇文章暂时写到这里了,简单的介绍了一些RecyclerView分隔线的原理和添加方法,希望大家能够多多交流,过几天我会继续写下一篇文章,RecyclerView系列之(3):为RecyclerView添加下拉刷新和上拉加载的功能。最后还是要感谢大家,感谢这个平台,能够让我们一起交流,一切学习。





作者:右眼皮的爱
链接: http://www.jianshu.com/p/4eff036360da
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/u013651026/article/details/81389841