GridLayoutManager均分网格

下面结论都是基于GridLayoutManager方向为竖直,spanCount为列数的情况,但在水平方向类似。

SpanSizeLookup

  • public int getSpanIndex(int position, int spanCount)
    返回值:position对应item所在列的起始index

  • public abstract int getSpanSize(int position)
    返回值:position对应item所跨越列的数量(所占spanCount的份额)

  • public int getSpanGroupIndex(int adapterPosition, int spanCount)
    返回值:position对应item所属组的index, 如果是竖直方向就表示所在的行号

假设一个grid为5列,有一个item在第二行,宽度从第二列开始到最后一列。
那么那么这个item宽度占了4列,所以getSpanSize等于4。
在第二行,所以getSpanGroupIndex等于1。
宽度从第二列开始,所以getSpanIndex等于1。

ItemDecoration

在使用decoration做间距,getItemOffsets方法中使用Rect为每个item分配间距,如果每个item的左右间距之和不相等,则会导致最终每个item不是均分。

假设每个item之间的间隔为a,记每个item左间距为L0,L1,L2....Ln-1,右间距为R0,R1,R2....Rn-1,n为网格列表的列数。

常数k= ((n-1)*a)/n,每个item分配间距分配到的间距之和。

第一列: L0 = 0, R0= k
第二列:L1 =a-R0, R1 = k-L1
第三列:L2 = a-R1,R2=k-L2
......
第N个:L(n-1) = a - R(n-2), R(n-1) = k-L(n-1)

通过上面关系可以通过整理一个方法

    private val cache = HashMap<Int, Pair<Int, Int>>()
   /**
     * 获取指定列的左右间距
     * @param columnIndex列的索引
     * @param itemSpace 每个item之间的间距
     * @param k 平分到每个item的左右间距之和
     * @return  Pair.first表示左间距,Pair.second表示右间距
     */
    private fun getHorizontalMargin(columnIndex: Int, itemSpace: Int, k: Int): Pair<Int, Int> {
        if (columnIndex == 0) {
            return 0 to k
        }

        var prev = cache[columnIndex - 1]
        if (prev == null) {
            prev = getHorizontalMargin(columnIndex - 1, itemSpace, k)
            cache[columnIndex-1] = prev
        }
        val left = itemSpace - prev.second
        val right = k - left
        return left to right
    }

其中

val k = (总列数 * space - space) / 总列数
val columnIndex = position % 总列数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容