引言

在以前使用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都在统一水平线上且垂直相隔的距离都是相等的。主要代码如下:

// set top to all in first lane
if (position < mCountInFirstLine) {
outRect.top = mSpace;
}
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. 由链表初始化看C语言的二级指针

    先来看C语言创建链表.插入节点和遍历链表的一段代码: #include <stdio.h> #include <stdlib.h> typedef int ElemType; ...

  2. Apache 一台主机绑定多个域名及虚拟主机

    今天研究了下Apache下如何使用一台主机绑定多个域名且使用80端口.说白了就是在一台主机上运行多个网站,并且网站域名都是使用的80端口. 具体方法如下: 1.进入Apache conf目录,找到ht ...

  3. java 新手

    public class hello{ public static void main(String args[]){ int a=23,b=32,c=34; int s=Math.max(a,c); ...

  4. 洛谷 P1026 统计单词个数

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...

  5. IOS开发中 RunLoop,RunTime

    1.Objective-C中的函数调用 对于C语言,函数调用是由编译器直接转化完成的,在编译时程序就开始查找要执行的函数(C语言函数调用原理).而在OC中,我们将函数调用称为消息发送.在编译时程序不查 ...

  6. 【机房重构】SQL之视图

    近期在重构机房收费系统,越往后就会越感觉到这里很多其它的是对之前学过知识(数据库,设计模式)的一种应用和回想.比方在登录功能中用到了抽象加反射,在学生下机中,我们能够用触发器来同一时候更新两个表.这里 ...

  7. C 语言中 typeof keyword简单介绍

    原文:http://hi.baidu.com/leowang715/blog/item/b0b96d6f972e7dd080cb4a06.html typeofkeyword是C语言中的一个新扩展.仅 ...

  8. WebLogic: The Definitive Guide examined WebLogic's security mechanisms--reference

    reference from: http://www.onjava.com/pub/a/onjava/excerpt/weblogic_chap17/index1.html?page=1 ...... ...

  9. [转] npm 模块安装机制简介

    npm 是 Node 的模块管理器,功能极其强大.它是 Node 获得成功的重要原因之一. 正因为有了npm,我们只要一行命令,就能安装别人写好的模块 . $ npm install 本文介绍 npm ...

  10. Android中多线程下载列表的封装实现(含进度反馈)

    来源:http://blog.csdn.net/u011638883/article/details/17347015 实现了一下Android中的文件多线程下载模块,支持自定义线程数.断点续传.下载 ...