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

来源:互联网 发布:mac bash 3.2 编辑:程序博客网 时间:2024/05/22 02:15

最近使用 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


阅读全文
0 0
原创粉丝点击