天天看點

自定義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);
        }
    }
}