需求說明
RecyclerView做網格布局時,設定RecyclerView的ItemDecoration,要求設定之後:
- 每個item的寬度和高度一緻
- 最左邊的item左邊無間隔
- 最右邊的item右邊無間隔
分析過程
1. 每個item左右應出比例的計算方式
假定兩個view之間需要的間距大小為space
- 如果是兩個item,則
- 第一個item:右邊出1/2*space的大小
- 第二個item:左邊出1/2*space的大小
- 如果是三個item,則
- 第一個item:右邊出2/3*space
- 第二個item:左邊出1/3space;右邊出1/3space
- 第三個item:左邊出2/3*space
- 如果是四個item,則
- 第一個item:右邊出3/4*space
- 第二個item:左邊出1/4space;右邊出2/4space
- 第三個item:左邊出2/3space;右邊出1/4space
- 第四個item:左邊出3/4*space
- 歸納總結:有n個item,計算第m個item左右應出的空間的方法
左邊=(n-1)/n*space*(m-1)
右邊=(n-1)/n*space*(n-m)
分析圖:

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);
}
}
}