天天看点

自定义RecyclerView的通用ItemDecoration需求说明分析过程SpaceItemDecoration代码如下

需求说明

RecyclerView做网格布局时,设置RecyclerView的ItemDecoration,要求设置之后:

  1. 每个item的宽度和高度一致
  2. 最左边的item左边无间隔
  3. 最右边的item右边无间隔

分析过程

1. 每个item左右应出比例的计算方式

假定两个view之间需要的间距大小为space

  1. 如果是两个item,则
    1. 第一个item:右边出1/2*space的大小
    2. 第二个item:左边出1/2*space的大小
  2. 如果是三个item,则
    1. 第一个item:右边出2/3*space
    2. 第二个item:左边出1/3space;右边出1/3space
    3. 第三个item:左边出2/3*space
  3. 如果是四个item,则
    1. 第一个item:右边出3/4*space
    2. 第二个item:左边出1/4space;右边出2/4space
    3. 第三个item:左边出2/3space;右边出1/4space
    4. 第四个item:左边出3/4*space
  4. 归纳总结:有n个item,计算第m个item左右应出的空间的方法
左边=(n-1)/n*space*(m-1)
右边=(n-1)/n*space*(n-m)
           

分析图:

自定义RecyclerView的通用ItemDecoration需求说明分析过程SpaceItemDecoration代码如下

2. 每个item上下应出比例的计算方式

推理过程如上

SpaceItemDecoration代码如下

/**
 * ------------------------------------------------
 * Copyright © 2014-2019 CLife. All Rights Reserved.
 * Shenzhen H&T Intelligent Control Co.,Ltd.
 * -----------------------------------------------
 *
 * @author huyongming
 * @version v1.4.0
 * @date 2019/7/2-19:02
 * @annotation 通用RecyclerView的分割线;
 * 使用注意:需要在notifyDataSetChanged之前,调用setSize(int size, int headerSize)方法,设置RecyclerView中网格部分的item的个数和第一个网格之前的item的个数
 */
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
    private int rowSpace;
    private int size;
    private int rowSize;
    private int headerSize;
    private int maxRow;
    private float lineSpaceBlank;
    private float rowSpaceBlank;

    /**
     * 构造函数
     *
     * @param lineSpace 列之间的间隔宽度
     * @param rowSpace  行之间的间隔宽度
     * @param rowSize   行的大小
     */
    public SpaceItemDecoration(int lineSpace, int rowSpace, int rowSize) {
        this.rowSpace = rowSpace;
        this.rowSize = rowSize;
        this.lineSpaceBlank = 1.0f / rowSize * lineSpace;
    }

    /**
     * 设置RecyclerView中网格部分的item的个数和第一个网格之前的item的个数
     *
     * @param size       RecyclerView中网格部分的item的个数
     * @param headerSize 第一个网格之前的item的个数
     */
    public void setSize(int size, int headerSize) {
        this.size = size;
        maxRow = (size + rowSize - 1) / rowSize;
        this.rowSpaceBlank = 1.0f / maxRow * rowSpace;
        this.headerSize = headerSize;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildLayoutPosition(view);
//            Logc.d("getChildLayoutPosition:" + position + ";size:" + size + ";headerSize:" + headerSize + ";rowSize:" + rowSize);
        if (position + 1 > headerSize && position + 1 - headerSize <= size) {
            int realPosition = position - headerSize;

            int modePosition = realPosition % rowSize;
            outRect.left = (int) (modePosition * lineSpaceBlank);
            outRect.right = (int) ((rowSize - 1 - modePosition) * lineSpaceBlank);

            int currentRow = realPosition / rowSize;
            outRect.top = (int) (currentRow * rowSpaceBlank);
            outRect.bottom = (int) ((maxRow - 1 - currentRow) * rowSpaceBlank);
        }
    }
}