RecyclerView ItemDecoration:间距和分隔符

时间:2016-07-14 11:57:01

标签: android android-recyclerview

下面是我如何为RecyclerView项目做间距。它旨在与网格和列表一起使用。间距有效。

我无法弄清楚的是如何插入分隔线。任何帮助都将非常感激。

SIDE注意:如果你有更好的方法来实现间距而不是我现在正在做的事情,我也非常感激:)

public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {

    private int numOfColumns;
    private int listSize;
    private int offsetInDp;
    private boolean isGridView;
    private boolean canScrollHorizontally;
    private boolean isBottomRow = false;


    public ItemOffsetDecoration(RecyclerView.LayoutManager manager, int listSize, int offsetInDp) {
        this(manager, 1, listSize, offsetInDp);
    }

    public ItemOffsetDecoration(RecyclerView.LayoutManager manager, int numOfColumns, int listSize, int offsetInDp) {
        this.numOfColumns = numOfColumns;
        this.listSize = listSize;
        this.offsetInDp = PixelConversionUtils.dpToPx(offsetInDp);

        this.isGridView = manager instanceof GridLayoutManager;
        this.canScrollHorizontally = manager.canScrollHorizontally();
    }

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

        // only do left/right spacing if grid or horizontal list
        if (isGridView || canScrollHorizontally) {
            outRect.left = offsetInDp;
            outRect.right = offsetInDp;
        }

        // only do top/bottom spacing if grid or vertical list
        if (isGridView || !canScrollHorizontally) {
            int pos = parent.getChildAdapterPosition(view);
            boolean isNotTopRow = pos >= numOfColumns;

            // Don't add top spacing to top row
            if (isNotTopRow) {
                outRect.top = offsetInDp;
            }

            int columnIndex = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();

            if (pos >= (listSize - numOfColumns) && columnIndex == 0) {
                isBottomRow = true;
            }

            // Don't add bottom spacing to bottom row
            if (!isBottomRow && pos < (listSize - numOfColumns)) {
                outRect.bottom = offsetInDp;
            }
        }
    }
}

这里是我想要做的快速视觉效果:

这就是我所拥有的:

enter image description here

这就是我想要的:

enter image description here

3 个答案:

答案 0 :(得分:2)

您可以通过这种方式获得所需的外观:

  • 首先,创建一个分隔符Drawable,对于这个例子,我使用了一个简单的形状,但你可以使用默认的行分隔符或任何其他drawable:

    <shape xmlns:android="http://schemas.android.com/apk/res/android" 
        android:shape="rectangle">
        <size android:height="2dp" />
        <size android:width="2dp" />
        <solid android:color="#000000" />
    </shape>
    
  • 第二,在你的ItemOffsetDecoration声明Drawable并初始化它:

    public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
    
        private Drawable mDivider;
    
        ...
    
        public ItemOffsetDecoration(...) {
            mDivider = ContextCompat.getDrawable(context, R.drawable.item_divider);
        }
    }
    
  • 第三,重写onDrawOver()方法:

    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (isGridView) {
            drawVerticalDivider(c, parent);
        } else {
            drawVerticalDivider(c, parent);
            drawHorizontalDivider(c, parent);
        }
    
    }
    

    drawVerticalDivider()&amp; drawHorizontalDivider()(通过参数将它们重构为分割器的单个方法和控制方向可能是个好主意):

    public void drawVerticalDivider(Canvas c, RecyclerView parent) {
        if (parent.getChildCount() == 0) return;
    
        final int childCount = parent.getChildCount();
    
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params =
                    (RecyclerView.LayoutParams) child.getLayoutParams();
    
            int left = child.getLeft() - params.leftMargin - offsetInDp;
            int right = child.getRight() + params.rightMargin + offsetInDp;
            int top = child.getBottom() + params.bottomMargin + offsetInDp;
            int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
    
    public void drawHorizontalDivider(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
    
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params =
                    (RecyclerView.LayoutParams) child.getLayoutParams();
    
            int left = child.getRight() + params.rightMargin + offsetInDp;
            int right = left + mDivider.getIntrinsicWidth();
            int top = child.getTop() - params.topMargin - offsetInDp;
            int bottom = child.getBottom() + params.bottomMargin + offsetInDp;
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
    

Linear和Grid LayoutManagers的结果:

LinearLayoutManager GridLayoutManager

答案 1 :(得分:0)

实际上,我曾尝试使用Divider,虽然有点有趣:首先让你使用深色的recycleview背景,然后让item_view背景为白色,然后为每个项目设置marginbottom - &gt;我是认真的,不要拒绝投票:)

searchResult()

答案 2 :(得分:0)

尝试放置以下XML代码段以获取分隔符:

<View android:layout_width="match_parent"
      android:layout_height="1dp"
      android:layout_marginLeft="72dp"
      android:layout_marginRight="16dp"
      android:background="123e4152"/>

您可以将它放在项目下方的recyclerView项目布局中。还可以使用边距和背景来适应您的列表。