RecyclerView之利用ItemDecoration实现万能间距

目前在Android开发中RecyclerView的使用率依然很高,提到RecyclerView就绕不开Item间距的问题,说实话,我在刚开始接触RecyclerView时,是给布局里设置margin来实现间距的(捂脸。。。现在想来自己是多么无知),直到后来发现人家RecyclerView早已洞穿一切,给我们提供了一个方法addItemDecoration:

public void addItemDecoration(ItemDecoration decor) {
        addItemDecoration(decor, -1);
    }

其中参数ItemDecoration是RecyclerView的一个静态抽象内部类,需要我们继承它,然后重写getItemOffsets方法,在这个方法中去设置我们需要的间距。下面我把我重写的CommonItemDecoration分享给大家,在这里边我已经根据RecyclerView的列数或行数对不同item的间距进行了计算,我称之为“万能间距”!使用时只需传入你想要的间距大小即可,代码如下:

import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;

/**
 * Description:RecyclerView的万能间距
 * Created by kang on 2018/3/9.
 */
public class CommonItemDecoration extends RecyclerView.ItemDecoration {
    private int horizontalSpace; // 整个RecyclerView与左右两侧的间距
    private int verticalSpace; // 整个RecyclerView与上下的间距
    private int leftMargin; // 每个item与左边的间距
    private int topMargin; // 每个item与顶部的间距
    private int rightMargin; // 每个item与右边的间距
    private int bottomMargin; // 每个item与底部的间距

    public CommonItemDecoration(int horizontalSpace, int verticalSpace) {
        this(horizontalSpace, verticalSpace, 0, 0, 0, 0);
    }

    public CommonItemDecoration(int horizontalSpace, int verticalSpace, int margin) {
        this(horizontalSpace, verticalSpace, margin, margin, margin, margin);
    }

    public CommonItemDecoration(int horizontalSpace, int verticalSpace, int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
        this.horizontalSpace = horizontalSpace;
        this.verticalSpace = verticalSpace;
        this.leftMargin = leftMargin;
        this.topMargin = topMargin;
        this.rightMargin = rightMargin;
        this.bottomMargin = bottomMargin;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        // 得到当前Item在RecyclerView中的位置,从0开始
        int position = parent.getChildAdapterPosition(view);
        // 得到RecyclerView中Item的总个数
        int count = parent.getAdapter().getItemCount();

        if (parent.getLayoutManager() instanceof GridLayoutManager) { // 网格布局
            GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
            // 得到网格布局的列数
            int spanCount = gridLayoutManager.getSpanCount();
            // 判断该网格布局是水平还是垂直
            if (LinearLayoutManager.VERTICAL == gridLayoutManager.getOrientation()) { // 垂直
                if (spanCount == 1) { // 列数为1
                    verticalColumnOne(outRect, position, count);
                } else { // 列数大于1
                    verticalColumnMulti(outRect, position, count, spanCount);
                }
            } else if (LinearLayoutManager.HORIZONTAL == gridLayoutManager.getOrientation()) { // 水平
                if (spanCount == 1) { // 行数为1
                    horizontalColumnOne(outRect, position, count);
                } else { // 行数大于1
                    horizontalColumnMulti(outRect, position, count, spanCount);
                }
            }
        } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { // 线性布局
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            if (LinearLayoutManager.VERTICAL == layoutManager.getOrientation()) { // 垂直
                verticalColumnOne(outRect, position, count);
            } else if (LinearLayoutManager.HORIZONTAL == layoutManager.getOrientation()) { // 水平
                horizontalColumnOne(outRect, position, count);
            }
        } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { // 流布局
            //TODO 瀑布流布局相关
        }
    }

    /**
     * 列表垂直且列数为1
     *
     * @param outRect  包括左上右下四个参数,分别控制view左上右下的margin
     * @param position 当前view所处位置
     * @param count    RecyclerView中Item的总个数
     */
    private void verticalColumnOne(Rect outRect, int position, int count) {
        if (position == 0) { // 位置为0时(即第一个Item),不设置底部间距
            outRect.set(leftMargin, topMargin, rightMargin, 0);
        } else if (position == count - 1) { // 最后一个Item
            outRect.set(leftMargin, verticalSpace, rightMargin, bottomMargin);
        } else { // 中间的Item,不设置底部间距
            outRect.set(leftMargin, verticalSpace, rightMargin, 0);
        }
    }

    /**
     * 列表垂直且列数大于1
     *
     * @param outRect   包括左上右下四个参数,分别控制view左上右下的margin
     * @param position  当前view所处位置
     * @param count     RecyclerView中Item的总个数
     * @param spanCount 布局的列数
     */
    private void verticalColumnMulti(Rect outRect, int position, int count, int spanCount) {
        // 通过计算得出总行数
        int totalRow = count / spanCount + ((count % spanCount) == 0 ? 0 : 1);
        // 计算得出当前view所在的行
        int row = position / spanCount;
        // 通过对position加1对spanCount取余得到column
        // 保证column等于1为第一列,等于0为最后一个,其它值为中间列
        int column = (position + 1) % spanCount;
        if (column == 1) {
            outRect.set(leftMargin,
                    row == 0 ? topMargin : verticalSpace,
                    horizontalSpace / 2,
                    row == totalRow - 1 ? bottomMargin : 0);
        } else if (column == 0) {
            outRect.set(horizontalSpace / 2,
                    row == 0 ? topMargin : verticalSpace,
                    rightMargin,
                    row == totalRow - 1 ? bottomMargin : 0);
        } else {
            outRect.set(horizontalSpace / 2,
                    row == 0 ? topMargin : verticalSpace,
                    horizontalSpace / 2,
                    row == totalRow - 1 ? bottomMargin : 0);
        }
    }

    /**
     * 列表水平且行数为1
     *
     * @param outRect  包括左上右下四个参数,分别控制view左上右下的margin
     * @param position 当前view所处位置
     * @param count    RecyclerView中Item的总个数
     */
    private void horizontalColumnOne(Rect outRect, int position, int count) {
        if (position == 0) { // 位置为0时(即第一个Item)
            outRect.set(leftMargin, topMargin, horizontalSpace / 2, bottomMargin);
        } else if (position == count - 1) { // 最后一个Item
            outRect.set(horizontalSpace / 2, topMargin, rightMargin, bottomMargin);
        } else { // 中间的Item
            outRect.set(horizontalSpace / 2, topMargin, horizontalSpace / 2, bottomMargin);
        }
    }

    /**
     * 列表水平且行数大于1
     *
     * @param outRect   包括左上右下四个参数,分别控制view左上右下的margin
     * @param position  当前view所处位置
     * @param count     RecyclerView中Item的总个数
     * @param spanCount 布局的行数
     */
    private void horizontalColumnMulti(Rect outRect, int position, int count, int spanCount) {
        // 通过计算得出总列数
        int totalColumn = count / spanCount + ((count % spanCount) == 0 ? 0 : 1);
        // 计算得出当前view所在的列
        int column = position / spanCount;
        // 通过对position加1对spanCount取余得到row
        // 保证row等于1为第一行,等于0为最后一个,其它值为中间行
        int row = (position + 1) % spanCount;
        if (row == 1) {
            outRect.set(column == 0 ? leftMargin : horizontalSpace / 2,
                    topMargin,
                    column == totalColumn - 1 ? rightMargin : horizontalSpace / 2,
                    0);
        } else if (row == 0) {
            outRect.set(column == 0 ? leftMargin : horizontalSpace / 2,
                    verticalSpace,
                    column == totalColumn - 1 ? rightMargin : horizontalSpace / 2,
                    bottomMargin);
        } else {
            outRect.set(column == 0 ? leftMargin : horizontalSpace / 2,
                    verticalSpace,
                    column == totalColumn - 1 ? rightMargin : horizontalSpace / 2,
                    0);
        }
    }

}
若想实现分割线效果,看我的下一篇文章!

猜你喜欢

转载自blog.csdn.net/k_bb_666/article/details/80738034