如何在Android RecyclerView中添加分割线?

263

我正在开发一个安卓应用程序,在其中使用了RecyclerView。我需要在RecyclerView中添加一个分隔线。 我尝试添加 -


recyclerView.addItemDecoration(new
     DividerItemDecoration(getActivity(),
       DividerItemDecoration.VERTICAL_LIST));

以下是我的 XML 代码 -

   <android.support.v7.widget.RecyclerView
    android:id="@+id/drawerList"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="15dp"
    />

3
我想这会对你有所帮助。https://dev59.com/KGAf5IYBdhLWcg3wdCl1 - Sanket Kachhela
1
要显示没有最后一行的分隔符,请使用这个 - Kishan Solanki
我认为你的代码是正确的。我没有看到任何问题。 - Rohit Rawat
25个回答

344

5
谢谢提供信息! 有没有办法在最后一个条目后面移除分隔符? 我的CardView中实现了列表,但是底部的分隔符和阴影看起来不好! - Maxi
7
我曾经也遇到同样的问题,通过扩展DividerItemDecoration并重写getItemOffsets方法解决了它,然后只有在不是第一个项目时才调用super。如果(parent.getChildAdapterPosition(view) == state.getItemCount() - 1),则返回,否则调用超类的getItemOffsets()方法。 - Robin
17
我使用了DividerItemDecoration.VERTICAL而不是mLayoutManager.getOrientation(),因为我的RecyclerView是垂直的,这样就可以正常工作了。 - Aaron Lelevier
3
有没有一种内置的方式可以改变分隔线的颜色? - j2emanue
1
优秀的答案,非常快速地添加分隔符的方法。 - arniotaki
显示剩余3条评论

247
正确的方法是为RecyclerView定义ItemDecoration,如下所示

SimpleDividerItemDecoration.java

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;
 
    public SimpleDividerItemDecoration(Context context) {
        mDivider = ContextCompat.getDrawable(context, R.drawable.line_divider);
    }
 
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
 
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
 
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
 
            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();
 
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
}

或者如果你正在使用 Kotlin: SimpleDividerItemDecoration.kt

class SimpleDividerItemDecoration(context: Context, @DrawableRes dividerRes: Int) : ItemDecoration() {

    private val mDivider: Drawable = ContextCompat.getDrawable(context, dividerRes)!!

    override fun onDrawOver(c: Canvas, parent: RecyclerView) {
        val left = parent.paddingLeft
        val right = parent.width - parent.paddingRight
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val child: View = parent.getChildAt(i)
            val params = child.layoutParams as RecyclerView.LayoutParams
            val top: Int = child.bottom + params.bottomMargin
            val bottom = top + mDivider.intrinsicHeight
            mDivider.setBounds(left, top, right, bottom)
            mDivider.draw(c)
        }
    }
}
    

line_divider.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
 
    <size
        android:width="1dp"
        android:height="1dp" />
 
    <solid android:color="@color/dark_gray" />
 
</shape>

最后设置成这样
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(this));

编辑

正如@Alan S.所指出的那样。

context.getResources().getDrawable(R.drawable.line_divider); 

已经过时,您可以使用

ContextCompat.getDrawable(context,R.drawable.line_divider);

3
context.getResources().getDrawable(R.drawable.line_divider)现在已经过时。 - Alan S.
2
没问题。这是一个很好的答案,对我非常有效。谢谢。 - Alan S.
3
这在我的端上完美地运作。但是,我想知道为什么不在每个单元格的布局中添加一个简单的<View>来作为分隔符呢?这样代码会少得多。这种解决方案在性能方面是否不太好?谢谢。 - Greg
4
如果您尝试滑动或移动物品,则此实现会出现问题。 - TerNovi
1
@NJ 谢谢老兄,你帮我省了不少时间。 - Suhas Bachewar
显示剩余5条评论

46

如果您想要同时拥有水平和垂直分割线:

  1. 定义水平和垂直分割线绘制图形:

    horizontal_divider.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
      <size android:height="1dip" />
      <solid android:color="#22000000" />
    </shape>
    

    vertical_divider.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
        <size android:width="1dip" />
        <solid android:color="#22000000" />
    </shape>
    
  2. 请将以下代码段添加到此处:

  3. DividerItemDecoration verticalDecoration = new DividerItemDecoration(recyclerview.getContext(),
            DividerItemDecoration.HORIZONTAL);
    Drawable verticalDivider = ContextCompat.getDrawable(getActivity(), R.drawable.vertical_divider);
    verticalDecoration.setDrawable(verticalDivider);
    recyclerview.addItemDecoration(verticalDecoration);
    
    DividerItemDecoration horizontalDecoration = new DividerItemDecoration(recyclerview.getContext(),
            DividerItemDecoration.VERTICAL);
    Drawable horizontalDivider = ContextCompat.getDrawable(getActivity(), R.drawable.horizontal_divider);
    horizontalDecoration.setDrawable(horizontalDivider);
    recyclerview.addItemDecoration(horizontalDecoration);
    

它起作用了。但是如果你将 horizontal_divider.xml 更改为分割宽度,将 vertical_divider.xml 更改为分割高度,那么你可以像这样创建每个 DividerItemDecorationverticalDecoration = new DividerItemDecoration(recyclerview.getContext(), DividerItemDecoration.VERTICAL);horizontalDecoration = new DividerItemDecoration(recyclerview.getContext(), DividerItemDecoration.HORIZONTAL); - Ruben O. Chiavone

43

所有这些答案都接近正确,但它们每个都缺失了一个关键细节。经过一番研究,我发现最简单的方法是结合以下三个步骤:

  1. 使用支持库的 DividerItemDecoration
  2. 创建具有正确颜色的分隔线
  3. 将此分隔线设置为您的主题的 listDivider

第1步:配置RecyclerView时

recyclerView.addItemDecoration(
        new DividerItemDecoration(context, layoutManager.getOrientation()));

步骤2:在类似 res/drawable/divider_gray.xml 的文件中

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size android:width="1px" android:height="1px" />
    <solid android:color="@color/gray" />
</shape>

步骤三:在应用程序的主题中

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Other theme items above -->
    <item name="android:listDivider">@drawable/divider_gray</item>
</style>

编辑:更新以跳过最后一个分隔符:
使用一段时间后,我意识到它在最后一项后面画了一个分隔符,这很烦人。所以我修改了步骤1,以覆盖DividerItemDecoration的默认行为(当然,创建一个单独的类是另一个选项):

recyclerView.addItemDecoration(
        new DividerItemDecoration(context, layoutManager.getOrientation()) {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                int position = parent.getChildAdapterPosition(view);
                // hide the divider for the last child
                if (position == parent.getAdapter().getItemCount() - 1) {
                    outRect.setEmpty();
                } else {
                    super.getItemOffsets(outRect, view, parent, state);
                }
            }
        }
);

9
覆盖getItemOffsets对我来说似乎没有起作用。即使我覆盖并且从未调用super,分隔线仍然会被绘制出来。不确定发生了什么改变。 - lostintranslation
3
它对我也不起作用。最后的分隔符仍然显示。 - Sotti
1
最终我通过复制DividerItemDecoration的源代码并进行一些修改来创建自己的分隔符类,以便不绘制最后一个分隔符。在绘制方法中,只需忽略最后一个子视图:将 for (int i = 0; i < childCount; i++) 更改为 for (int i = 0; i < childCount - 1; i++) - kientux
由于ItemDecoration是在列表项之前绘制的(“在”列表项之下),所以给定的解决方案仅在您的列表项具有100%不透明背景或装饰可绘制物体为100%透明(因此用户可以看到recyclerView的背景)时起作用。否则,无论您在getItemOffsets()中返回什么,分隔线都是可见的。 - ernazm

43

只需在您的项适配器末尾添加一个视图:

<View
 android:layout_width="match_parent"
 android:layout_height="1dp"
 android:background="#FFFFFF"/>

35
使用此解决方案,您将在列表末尾还获得分隔线。 - Arià
9
在onBindViewHolder中可以通过像这样的代码来移除最后一行:if(position == getItemCount() - 1) { mDividerView.setVisibility(View.INVISIBLE) } 当然,还有其他方法可以实现此功能。 - Ali Kazi
大多数情况下,高度为1px的最后一行对我们的眼睛来说是不可见的。 - Mehdi Khademloo
@LucasDiego 这个方法可以运行,但我们知道膨胀是很耗费资源的。 - Zohra Khan
1
这不是最佳解决方案,因为它仅在RecyclerView中的元素数量不太多时才能正常工作。否则,视图将无法为每个元素绘制。因此,请使用DividerItemDecoration。 - Neckster

24

这是一个简单的自定义分割线代码(垂直分割线 / 高度为1dp / 黑色):

假设您已经拥有Support Library:

compile "com.android.support:recyclerview-v7:25.1.1"

Java 代码

    DividerItemDecoration divider = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
    divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.my_custom_divider));
    recyclerView.addItemDecoration(divider);

然后是custom_divider.xml文件示例:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@android:color/black" />
</shape>

22

Kotlin 版本:

recyclerview.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))

20

我处理分割视图和分割插图的方式是通过添加一个RecyclerView扩展。

1.

通过命名View或RecyclerView来添加一个新的扩展文件:

RecyclerViewExtension.kt

并在 RecyclerViewExtension.kt 文件中添加 setDivider 扩展方法。

/*
* RecyclerViewExtension.kt
* */
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView


fun RecyclerView.setDivider(@DrawableRes drawableRes: Int) {
    val divider = DividerItemDecoration(
        this.context,
        DividerItemDecoration.VERTICAL
    )
    val drawable = ContextCompat.getDrawable(
        this.context,
        drawableRes
    )
    drawable?.let {
        divider.setDrawable(it)
        addItemDecoration(divider)
    }
}

2.

drawable 包内创建一个名为 recycler_view_divider.xml 的可绘制资源文件:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="10dp"
    android:insetRight="10dp">

    <shape>
        <size android:height="0.5dp" />
        <solid android:color="@android:color/darker_gray" />
    </shape>

</inset>

android:insetLeftandroid:insetRight中指定左右边距

3.

在初始化RecyclerView的Activity或Fragment中,您可以通过调用以下方法来设置自定义drawable:

recyclerView.setDivider(R.drawable.recycler_view_divider)

4.

干杯!

带分隔线的RecyclerView行。


11
res/drawable文件夹中创建一个单独的xml文件。
 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@android:color/black" />
</shape>

像这样在主活动中连接那个xml文件(your_file):

DividerItemDecoration divider = new DividerItemDecoration(
    recyclerView.getContext(),
    DividerItemDecoration.VERTICAL
);
divider.setDrawable(ContextCompat.getDrawable(getBaseContext(), R.drawable.your_file));
recyclerView.addItemDecoration(divider);

如何添加填充?在形状中使用填充无效。 - Makalele

9

试试这个简单的单行代码。

recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),LinearLayoutManager.VERTICAL)); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接