GridLayoutManager画分割块,同时不影响item内容的宽高

最近使用 RecyclerView + GridLayoutManager 时,需要 使用 ItemDecoration 画分割块, 当分割块的宽高稍微大一点之后 ,发现 各个 item的宽高不相同。


我也参考过网上 很多 讲解 ItemDecoration 的例子,  这些例子都太片面, 但这也很正常, 它只是要教会你 ItemDecoration的基本用法,能实现一个差不多功能就行。 这些例子  大多数 把  分割块 的宽度 设置成  1px 或 1dp 到 3dp, 导致  根本看不出 各个 item的宽度 不一致。

大名鼎鼎的鸿洋大神的那篇csdn博客画gridLayoutManager分割线,当把 分割线宽度设置成 30dp时,明显发现 最后一个 item的 内容宽度  变大了, 因此也有问题。不信的可自己去试试。



getItemOffsets(Rect outRect , xxxxxxxxx)  方法里的  Rect  实际上相当于给  itemView 设置了一个 Margin,  但 itemView的 最大宽高 是   屏幕宽度的   spanCount分之一。 


那如何 实现一个 自适应 任意列数的  ItemDecoration, 这里提供一个 很 巧妙的 实现方式, 源码如下:


/**
 * 自适应任意列的 GridLayoutManager 的分割块 ItemDecoration
 * Created by meikai on 2017/11/07.
 */
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int dividerWidth;
    private int dividerWidthTop;
    private int dividerWidthBot;

    private Paint dividerPaint;

    /**
     * @param spanCount gridLayoutManager 列数
     * @param dividerWidthDp 分割块宽高,单位:dp
     */
    public GridSpacingItemDecoration(Context context, int spanCount, int dividerWidthDp) {
        this.spanCount = spanCount;

        this.dividerPaint = new Paint();
        this.dividerPaint.setColor(Color.BLUE);

        this.dividerWidth = DensityUtil.dp2px(context, dividerWidthDp);
        this.dividerWidthTop = dividerWidth / 2;
        this.dividerWidthBot = dividerWidth - dividerWidthTop;
    }

    @Override
    public void getItemOffsets(Rect outRect, View child, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, child, parent, state);

        int pos = parent.getChildAdapterPosition(child);
        int column = (pos) % spanCount;// 计算这个child 处于第几列


        outRect.top = dividerWidthTop;
        outRect.bottom = dividerWidthBot;

        outRect.left = (column * dividerWidth / spanCount);
        outRect.right = dividerWidth - (column + 1) * dividerWidth / spanCount;

        Log.e("getItemOffsets", "pos=" + pos + ", column=" + column + " , left=" + outRect.left + ", right="
                + outRect.right + ", dividerWidth=" + dividerWidth);
    }

}


这个算法 精妙的 地方 在 这两句 :

outRect.left = (column * dividerWidth / spanCount);
outRect.right = dividerWidth - (column + 1) * dividerWidth / spanCount;

任意一个 child  的  left  值  跟它的  列数关联起来,  这个 child 的 right = 分割块的宽度 减去  下一列的left 。  

结论:分割块的实际宽度 = 上一个child的right + 下一个child的 left. 


例如:以5列显示的 gridLayoutManager 为例,要求 最左边和最右边 无分割块,中间每一个分割块的宽度相同,   则枚举每一个item的左右边距的值如下:

             左边距 右边距

第1列      0/5       4/5

第2列      1/5       3/5

第3列       2/5      2/5

第4列       3/5      1/5

第5列       4/5      0/5


其中 第1列的右边距 + 第2列的左边距 =  4/5 + 1/5 = 1个单位的 分割块宽度。


至于如何推导出这个算法,我也不得而知, 是最近在  stackoverflow 上找到的,我想应该是有个 推导过去, 最主要的思想是把   left 和 right 的值  与 列索引  关联起来。这样就能自适应任意列数的 gridLayoutManager 了。

下面是  stack overflow 的 链接:

https://stackoverflow.com/questions/28531996/android-recyclerview-gridlayoutmanager-column-spacing


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值