引言

在以前使用ListView和GridView时,设置item之间的间距还是相对比较简单的,因为它们的基本属性里面Android已经定义好了,可以直接设置属性值即可。但Google为了通用性和灵活性(至少我是这么认为-.-),对于V7包中的RecycleView来说,则需要自己实现ItemDecoration类的getItemOffsets(Rect outRect, View view,... ...)抽象方法。

局限

下面的推理只限于VERTICAL情况,至于HORIZONTAL情况的考虑方式应该是类似,大家就自行去考虑把,嘿嘿o(∩_∩)o

推理

嗯,接下来就是根据不同的布局情况找到item的outRect的计算规律(outRect负责存储item之间间距)。

首先对于RecycleView的LayoutManager为LinearLayoutManager,或者为GridLayoutManager但spanCount为1的情况先忽略,因为太简单了=。= 。

我们接下的考虑重点是当RecycleView的LayoutManager为GridLayoutManager且spanCount大于1的情况(暂且默认每个Item的spanSize的大小都为1,后面为具体讨论)。

其实仔细观察后你会发现,outRect的top和bottom计算远比right和left简单的多,因为在VERTICAL情况下,高度是没有限制的,所以我们计算时需要保证只对第一行的item的outRect.top赋值,对每个item的outRect.bottom都赋值即可,这样就可以保证每行item都在统一水平线上且垂直相隔的距离都是相等的。主要代码如下:

  1. // set top to all in first lane
  2. if (position < mCountInFirstLine) {
  3. outRect.top = mSpace;
  4. }
  5. outRect.bottom = mSpace;

对于outRect的right和left的计算,首先要明确的是三个已知条件,分别如下:

假设每个item间的左右间距为D(D>=0,常量),一共有n个item(1,2,3,... ... n),第i个item的左间隔距离为 \(x_{i}\),右间隔距离为\(y_{i}\) (1<=i<=n,i为自然数) 。

  1. $ x_{i}+ y_{i}=d (1<=i<=n,i为自然数,d为未知正数)$

  2. \(y_{i}+x_{i+1}=D(1<i<=n)\)

  3. \(x_{1}=D, y_{1}=D\)

其中需要说明的是,由于每个item的原始宽度一致,要使得每个item的左右边距在空出相应距离后仍宽度一致,则公式1一定成立,具体示意图如下:

由图可知,自然的我们可以很快的找到一个等式①,即:

\[x_{1}+y_{1}+x_{2}+y_{2}+... ...+x_{n}+y_{n}=(n+1)*D
\]

而由公式1可知:$$x_{i}+ y_{i}=d,即y_{i}=d-x_{i}$$

所以等式①为:$$nd=(n+1)D,即d=D+D/n$$

这就是d的计算公式,当然到这里证明还没有结束,我们联合公式1公式2可知:$$x_{i+1}-x_{i}+d=D,即x_{i+1}-x_{i}=-D/n(其中0<i<n,n>=1)$$

显然这是一个标准的等差数列,同时由公式3可知:\(x_{1}=D\),则第i个item的左间隔距离计算公式为:$$x_{i}=D-D/ni(其中0<i<=n,n>=1)$$再由公式1等式①即可推得$$y_{i}=D/n+D/ni(其中0<i<=n,n>=1)$$至此关于item的左右间隔距离的计算公式基本证明结束。

进一步推理

当然上述的推理结果是默认每个Item的spanSize的大小都为1为前提条件进行的,所以为了公式更加通用,下面我们具体讨论当spanSize大小不固定的情况。

首先需要明确的是spanSize的大小并不影响item的outRect.top和outRect.bottom的计算(原因可自行脑补=.=)。

而当每个item的spansize大小不一样时,关于item的outRect.left和outRect.right的计算其实和spanSize=1的情况是基本一样的,我们只需要换个思维方式,即一个spanSize=N的item可以看作是N个spanSize=1的item,其中N>0,且N为自然数,$$item_{spanSize=N}的x=x_{1}$$$$item_{spanSize=N}的y=y_{N}$$

具体公式如下:$$x_{i}=D-D/nai(其中0<ai<=n,n>=1)$$ $$y_{i}=D/n+D/n(ai+item_{i的spanSize}-1)(其中0<ai<=n,n>=1)$$

其中需要注意的是ai表示的该item在一行中的实际位置,即若第一个\(item_{spanSize=2}\)的ai=1时,第二个\(item\)的ai=3。

OK,至此公式的推理全部结束,有关示例源码下载连接

题外

唉,当初理清这些关系真的是花了好久(主要是好久不做数学题,生疏了-。-),希望能给大家提供些帮助,当然若有不足的地方欢迎指正。

这是搬到上海来写的第一篇文章,真的是“憋”了好久(─.─)|||,以后得更加勤快些,不能颓废下来。

作者:XycZero

查看原文:http://www.xyczero.com/blog/article/23/.

如何自定义RecycleView item的间距的更多相关文章

  1. 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)

    AsyncTask使用方法详情:http://www.cnblogs.com/zzw1994/p/4959949.html 下拉开源框架PullToRefresh使用方法和下载详情:http://ww ...

  2. iOS11UINavigationBar的item左右间距调整

    相信很多同学都知道在iOS7之后调整导航栏两侧按钮距离左右间距,其实就是在左右barButtonItem的数组中添加一个宽度为负的占位item. - (void)addLeftBarButtonIte ...

  3. Android 自定义TextView 实现文本间距

    Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...

  4. NGUI 自定义 Drag Item Script

    最近要实现一个NGUI效果. 查看了一下,NGUI有个自带 UIDragDropItem.cs 的组件进过修改后即可以实现. 下面贴上UI布局,代码: mDragDropItem.cs using U ...

  5. Typora 自定义主题 修改左右间距

    打开偏好设置,打开主题文件夹 比如要修改night主题中的间距,编辑night.css文件,修改#write样式即可. 修改其他样式类试.

  6. Android 自定义ListView Item侧滑删除

    本程序是基于网上开源项目修改而来,具体来源忘了,懒得搜了,如果有不合适的地方,请原作者联系我,我会及时回复和处理的! 该例子程序中主要包含两个ListView,一个是实现侧滑删除,一个是侧滑出菜单,代 ...

  7. Android ExpandableListView group的item有间距child间隔不变

    <ExpandableListView android:id="@+id/lv" android:layout_width="fill_parent" a ...

  8. Android recycleview item水波纹效果

    item的xml 根标签下添加如下三个属性 android:clickable="true" android:focusable="true" android: ...

  9. listview自定义背景以及item自定义背景

    item向自定义背景,可以根据position来设置不同的背景. listview背景设置是需要注意设置下面这几项: //点下时整个页面的背景 android:cacheColorHint=" ...

随机推荐

  1. hdoj 1010 Tempter of the Bone【dfs查找能否在规定步数时从起点到达终点】【奇偶剪枝】

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  2. 使用JavaScript扫描端口

    <html>    <title>端口扫描</title>    <head></head><form><label fo ...

  3. git 分支策略

    转 http://www.ruanyifeng.com/blog/2012/07/git.html  作者: 阮一峰 如果你严肃对待编程,就必定会使用"版本管理系统"(Versio ...

  4. C# Timer执行方法

    private void button3_Click(object sender, EventArgs e) { System.Timers.Timer t = new System.Timers.T ...

  5. 【Android - 框架】之Fresco的使用

    当下有很多图片加载框架,常见的有Glide.Fresco.Picasso等.Glide因为其体积小.缓存机制强大等优点,受到了广大程序员的青睐:Fresco虽然体积比较大,缓存机制也没有Glide强大 ...

  6. WCF - 序列化

    数据是信息的载体 在不同环境中有不同的类型 为保证处于不同平台的的应用能够正常的进行数据交互 必须采用一种双方都能理解的数据类型 XML无疑是最好的选择 但不是唯一的选择 例如JSON也是一种普遍认可 ...

  7. 前端高性能滚动 scroll 及页面渲染优化

    前言 最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作.本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲 ...

  8. Android开发:最详细的 NavigationDrawer 开发实践总结

    最详细的 NavigationDrawer 开发实践总结 继前面写的两篇文章之后(有问题欢迎反馈哦): Android开发:Translucent System Bar 的最佳实践 Android开发 ...

  9. xslt语法之---If Else

    大家都知道,XSL中是没有if else的,那么要想实现if else该怎么办呢? 其实很简单 <xsl:choose> <xsl:when test="position( ...

  10. Dreamweaver cs6安装破解

    Dreamweaver 是前端开发的必备软件.目前最新版本为CS6,与CS5相比多了对HTML5.CSS3.jquery的关联支持,可以更方便的在Dreamweaver中编写前端代码. 安装准备: 1 ...