在RecyclerView中为分隔线添加边距

42

我正在开发一个使用RecyclerView的安卓应用程序。我想要为RecyclerView添加分隔线,我使用了以下代码:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

目前一切都运行良好。但是分隔线占据了整个屏幕的大小,我想为其添加边距。有没有办法可以通过一种方法为分隔线添加边距,以便在绘制的矩形中添加一些间距,而不是创建一个带有边距的自定义可绘制形状并将其添加到RecyclerView中?


使用自定义的dividerItemDecoration。 - Vishal Patoliya ツ
3
看这个答案。迄今为止最好且最简单的解决方案。 - Bamerza
10个回答

76

我认为最直接的解决方案是在Decoration对象上使用setDrawable方法,并传入一个具有所需边距的插图drawable。像这样:

int[] ATTRS = new int[]{android.R.attr.listDivider};

TypedArray a = context.obtainStyledAttributes(ATTRS);
Drawable divider = a.getDrawable(0);
int inset = getResources().getDimensionPixelSize(R.dimen.your_margin_value);
InsetDrawable insetDivider = new InsetDrawable(divider, inset, 0, inset, 0);
a.recycle();

DividerItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
itemDecoration.setDrawable(insetDivider);
recyclerView.addItemDecoration(itemDecoration);

5
天才!非常感谢! - Dmitry Smolyaninov
2
如果可以重用和修改现有的ItemDecoration,请不要自己实现一个。简单明了的答案,不需要进行实现。 - Martin Edlman
1
当调用obtainStyledAttributes时,我遇到了OOM问题。我正在使用Kotlin。 - npk
我该如何设置这个分隔线的高度,使它更加粗? - E.Akio
@On_my_way_to_Dev_Life 你可能需要修改源可绘制对象使其更加粗细。 - SeptimusX75
显示剩余3条评论

21

形状.xml

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

layer.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/shape"
        android:left="16dp"
        android:right="16dp" />

</layer-list>

代码

val itemDecoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
itemDecoration.setDrawable(resources.getDrawable(R.drawable.layer, null))
recyclerView.addItemDecoration(itemDecoration)

1
这是在Recycler View中添加分隔线边距的最简单解决方案。 - Sunita
1
使用嵌入式:https://dev59.com/BlkS5IYBdhLWcg3wDyr5#40434249 - Zhou Hongbo

15

根据您的需求使用此功能并进行自定义。

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    private Drawable divider;

    /**
     * Default divider will be used
     */
    public DividerItemDecoration(Context context) {
        final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
        divider = styledAttributes.getDrawable(0);
        styledAttributes.recycle();
    }

    /**
     * Custom divider will be used
     */
    public DividerItemDecoration(Context context, int resId) {
        divider = ContextCompat.getDrawable(context, resId);
    }

    @Override
    public void onDraw(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 + divider.getIntrinsicHeight();

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }
}

在我的情况下,它只会在最后一项之后显示一次。 - Makalele

6

您可以为RecyclerView创建自己的项目装饰。以下是相应的代码。

public class SimpleItemDecorator extends RecyclerView.ItemDecoration {

    int space;
    boolean isHorizontalLayout;
    public SimpleItemDecorator(int space) {
        this.space = space;
    }

    public SimpleItemDecorator(int space, boolean isHorizontalLayout) {
        this.space = space;
        this.isHorizontalLayout = isHorizontalLayout;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if(isHorizontalLayout)
        {
            outRect.bottom=space;
            outRect.right=space;
            outRect.left=space;
            outRect.top=space;

        } else {
            outRect.bottom = space;
            if (parent.getChildAdapterPosition(view) == 0)
                outRect.top = space;
            else
                outRect.top = 0;

        }


    }
}

如果要在RecyclerView中使用它,可以像这样操作:

 recyclerView.addItemDecoration(new SimpleItemDecorator(5));

好的...那它如何绘制任何东西?该片段中没有分隔符。 - Sever
@Sever 它只是添加了空格,没有绘制任何内容。 - Vivek Mishra

6

进一步解释@SeptimusX75所说的:如果你(像我一样)喜欢用XML来做UI,那么你可以创建一个插入式可绘制文件。你需要创建第二个XML文件,但由于代码变得更加简洁,所以我认为这是值得的 :-).

[更新] 正如用户@Zhou Hongbo在评论中建议的那样,只使用一个XML文件:divider.xml:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/divider_base"
    android:insetRight="20dp"
    android:insetLeft="20dp">

    <shape>
        <android:shape="rectangle">
        <size android:height="1dp" />
        <solid android:color="@color/dividerColor" />
    </shape>

</inset>
(实际分隔符):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@color/dividerColor" />
</shape>

divider.xml (内嵌)

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/divider_base"
    android:insetRight="20dp"
    android:insetLeft="20dp">
</inset>

1
这两个文件可以合并~ https://dev59.com/BlkS5IYBdhLWcg3wDyr5#40434249 - Zhou Hongbo

4
我找到了最好、最简单的解决方案。
<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:insetLeft="40dp"
       android:insetRight="40dp" >
    <shape>
        <size android:height="1dp"/>
        <solid android:color="@color/recyclerview_divider" />
    </shape>
</inset>

从:https://dev59.com/BlkS5IYBdhLWcg3wDyr5#40434249

3
与@Vivek的答案类似,但使用Kotlin并具有不同的参数。
class SimpleItemDecorator : RecyclerView.ItemDecoration {

    private var top_bottom: Int = 0
    private var left_right: Int = 0

    /**
     * @param top_bottom for top and bottom margin
     * @param left_right for left and right margin
     */
    constructor(top_bottom: Int, left_right: Int = 0) {
        this.top_bottom = top_bottom
        this.left_right = left_right
    }

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.bottom = top_bottom
        outRect.top = top_bottom
        outRect.right = left_right
        outRect.left = left_right
    }
}

3

以下是一个简单的 Kotlin 代码片段,用于实现在 RecyclerView 中使用 ItemDecoration

 recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
                override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
                    outRect.left = 20    // Left Margin.
                    outRect.right = 20   // Right Margin.
                    outRect.top = 16     // Top Margin.
                    outRect.bottom = 16  // Bottom Margin.
                }
            })
说明:在上面的示例代码中,我们从四个方向为RecyclerView的每个项添加了边距。

编码愉快...


0
只需在您的RecyclerView中添加paddingStartpaddingEnd即可。它与DividerItemDecoration完美配合使用。

0

以下是带有左边距的RecyclerView分隔符代码。只需将代码粘贴到MainActivityOnCreate方法中即可。

class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;

    public SimpleDividerItemDecoration(Context context) {
        mDivider = context.getResources().getDrawable(R.drawable.divider);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = 250;
        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);
        }
    }
}

recyclerView.addItemDecoration(new SimpleDividerItemDecoration(
            getApplicationContext()));

由于您的drawable文件夹中缺少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/divider" />

</shape>

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