RecyclerView间距设置

本文介绍了一种适用于 RecyclerView 的 GridLayoutManager 的自定义 ItemDecoration 类,该类允许开发者为网格布局中的项设置不同的横向和纵向间距,并支持为最后一行或列设置特定的间距。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

适用于GridLayoutManager横竖间隔均可设置;

用法:

rv.addItemDecoration(new DividerGridItemDecoration(Color.TRANSPARENT, 30, 30, Color.TRANSPARENT, 0));

DividerGridItemDecoration类:

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;

    private int mDividerHSpacing;

    private int mDividerVSpacing;

    private Drawable mLastDivider;

    private int mLastDividerSize;

    public DividerGridItemDecoration() {
        set(new ColorDrawable(Color.TRANSPARENT), mDividerHSpacing, mDividerVSpacing, new ColorDrawable(Color.TRANSPARENT), mLastDividerSize);
    }

    public DividerGridItemDecoration(int horizaontalSpacing, int verticalSpacing, int lastDividerSize) {
        set(new ColorDrawable(Color.TRANSPARENT), horizaontalSpacing, verticalSpacing, new ColorDrawable(Color.TRANSPARENT), lastDividerSize);
    }

    public DividerGridItemDecoration(Drawable divider, int horizaontalSpacing, int verticalSpacing, Drawable lastDivider, int lastDividerSize) {
        set(divider, horizaontalSpacing, verticalSpacing, lastDivider, lastDividerSize);
    }

    public DividerGridItemDecoration(@ColorInt int dividerColor, int horizaontalSpacing, int verticalSpacing, @ColorInt int lastDividerColor, int lastDividerSize) {
        set(new ColorDrawable(dividerColor), horizaontalSpacing, verticalSpacing, new ColorDrawable(lastDividerColor), lastDividerSize);
    }

    /**
     * @param divider
     * @param horizaontalSpacing 横向间距
     * @param verticalSpacing    纵向间距
     * @param lastDivider
     * @param lastDividerSize    最后一行的后边距离,大于0才会生效
     */
    private void set(Drawable divider, int horizaontalSpacing, int verticalSpacing, Drawable lastDivider, int lastDividerSize) {
        this.mDivider = divider;
        this.mDividerHSpacing = horizaontalSpacing;
        this.mDividerVSpacing = verticalSpacing;
        this.mLastDivider = lastDivider;
        this.mLastDividerSize = lastDividerSize;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (mDivider == null) {
            return;
        }
        if (mDividerHSpacing > 0) {
            drawHorizontalSpacing(c, parent);
        }
        if (mDividerVSpacing > 0) {
            drawVerticalSpacing(c, parent);
        }
        if (mLastDividerSize > 0) {
            drawLastSpacing(c, parent);
        }
    }

    /**
     * 绘制横向间距,不包括最后一列
     *
     * @param c
     * @param parent
     */
    private void drawHorizontalSpacing(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            // 前边不用考虑是否是最后一列
            if (i < childCount - ((GridLayoutManager) parent.getLayoutManager()).getSpanCount()
                    || (parent.getLayoutManager().canScrollVertically() || !isLastGridRaw(parent, child))) {
                drawHorizontal(c, child, mDivider, mDividerHSpacing);
            }
        }
    }

    private void drawHorizontal(Canvas c, View child, Drawable divider, int spacing) {
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        final int left = child.getRight() + params.rightMargin;
        final int right = left + spacing;
        final int top = child.getTop() - params.topMargin;
        final int bottom = child.getBottom() + params.bottomMargin;
        divider.setBounds(left, top, right, bottom);
        divider.draw(c);
    }

    /**
     * 绘制纵向间距,不包括最后一行
     *
     * @param c
     * @param parent
     */
    private void drawVerticalSpacing(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            // 前边不用考虑是否是最后一行
            if (i < childCount - ((GridLayoutManager) parent.getLayoutManager()).getSpanCount()
                    || (parent.getLayoutManager().canScrollHorizontally() || !isLastGridRaw(parent, child))) {
                drawVertical(c, child, mDivider, mDividerVSpacing);
            }
        }
    }

    private void drawVertical(Canvas c, View child, Drawable divider, int spacing) {
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        final int left = child.getLeft() - params.leftMargin;
        final int right = child.getRight() + params.rightMargin;
        final int top = child.getBottom() + params.bottomMargin;
        final int bottom = top + spacing;
        divider.setBounds(left, top, right, bottom);
        divider.draw(c);
    }

    /**
     * 绘制最后
     *
     * @param c
     * @param parent
     */
    private void drawLastSpacing(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        int i = childCount - ((GridLayoutManager) parent.getLayoutManager()).getSpanCount();
        for (; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            if (isLastGridRaw(parent, child)) {
                if (parent.getLayoutManager().canScrollHorizontally()) {
                    drawHorizontal(c, child, mLastDivider, mLastDividerSize);
                } else if (parent.getLayoutManager().canScrollVertically()) {
                    drawVertical(c, child, mLastDivider, mLastDividerSize);
                }
            }
        }

    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
        if (gridLayoutManager.canScrollHorizontally()) {
            if (isLastGridRaw(parent, view)) {// 如果是最后一列
                if (parent.getChildAdapterPosition(view) == gridLayoutManager.getItemCount() - 1) {// 最后一个
                    outRect.set(0, 0, mLastDividerSize, 0);
                } else {
                    outRect.set(0, 0, mLastDividerSize, mDividerVSpacing);
                }
            } /*
                 * else if (RecyclerViewUtil.isLastGridColum(parent, view)) {//
             * 如果是最后一行,则不需要绘制底部 outRect.set(0, 0, mDividerHSpacing, 0); }
             */ else {
                outRect.set(0, 0, mDividerHSpacing, mDividerVSpacing);
            }
        } else if (gridLayoutManager.canScrollVertically()) {
            if (isLastGridRaw(parent, view)) {// 如果是最后一行,则不需要绘制底部
                if (parent.getChildAdapterPosition(view) == gridLayoutManager.getItemCount() - 1) {
                    outRect.set(0, 0, 0, mLastDividerSize);
                } else {
                    outRect.set(0, 0, mDividerHSpacing, mLastDividerSize);
                }
            } /*
                 * else if (RecyclerViewUtil.isLastGridColum(parent, view)) {//
             * 如果是最后一列,则不需要绘制右边 outRect.set(0, 0, 0, mDividerVSpacing); }
             */ else {
                outRect.set(0, 0, mDividerHSpacing, mDividerVSpacing);
            }
        }

    }

    /**
     * 是否是最后一行,相对于recyclerView的方向而言,横向表示最右边,竖向表示最下边
     *
     * @param parent
     * @param view
     * @return
     */
    public boolean isLastGridRaw(RecyclerView parent, View view) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookUp = gridLayoutManager.getSpanSizeLookup();
            int childPosition = parent.getChildAdapterPosition(view);
            int itemCount = gridLayoutManager.getItemCount();
            int spanCountTotal = 0;
            int spanCountChild = 0;
            if (childPosition >= itemCount - gridLayoutManager.getSpanCount()) {
                for (int i = 0; i < itemCount; i++) {
                    spanCountTotal += spanSizeLookUp.getSpanSize(i);
                    if (i <= childPosition) {
                        spanCountChild += spanSizeLookUp.getSpanSize(i);
                    }
                }
                int lastRowCount = spanCountTotal % gridLayoutManager.getSpanCount();
                if (lastRowCount == 0) {
                    lastRowCount = gridLayoutManager.getSpanCount();
                }
                if (spanCountChild > spanCountTotal - lastRowCount) {
                    return true;
                }
            }

        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            // TODO: 17/1/16
        }
        return false;
    }
}



在 Android 开发中,可以通过设置 RecyclerView间距来调整其显示效果。下面是一些实现方法: 1. 在 RecyclerView 的 item 布局文件中添加 margin 属性。例如,在 LinearLayout 布局中,可以通过设置 android:layout_marginTop、android:layout_marginBottom、android:layout_marginLeft、android:layout_marginRight 属性来设置上下左右的间距。 2. 通过 RecyclerView.ItemDecoration 实现间距设置。自定义一个 RecyclerView.ItemDecoration 类,重写 onDraw() 和 getItemOffsets() 方法,在 getItemOffsets() 方法中设置 item 之间的间距。 ```java public class MyItemDecoration extends RecyclerView.ItemDecoration { private int space; public MyItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = space; outRect.right = space; outRect.bottom = space; if (parent.getChildLayoutPosition(view) == 0) { outRect.top = space; } else { outRect.top = 0; } } } ``` 在 RecyclerView 的代码中调用 setItemDecoration() 方法,将自定义的 MyItemDecoration 类传入即可。 ```java recyclerView.addItemDecoration(new MyItemDecoration(10)); ``` 3. 使用 RecyclerView 的 LayoutManager 来实现间距设置。例如,使用 LinearLayoutManager 的 setPadding() 和 setClipToPadding() 方法来设置间距。 ```java LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); recyclerView.setPadding(10, 10, 10, 10); recyclerView.setClipToPadding(false); ``` 以上是三种常用的设置 RecyclerView 间距的方法,可以根据具体需求选择适合自己的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值