引言

在以前使用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. 关于python的开发工具——Canopy

    在学习和使用scikit-learn过程中,官方文档中推荐了两个IDE(Canopy and Anaconda),我分别在win7和mac下安装后,发现Canopy是可以用的.Anaconda没搞明白 ...

  2. nyoj 102 次方求模【快速幂】

    次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 求a的b次方对c取余的值   输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一 ...

  3. list,set,map,数组间的相互转换

    1.list转set Set set =  new  HashSet( new  ArrayList()); 2.set转list List list =  new  ArrayList( new   ...

  4. hdu 1242 dfs/bfs

    Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is ...

  5. java第四周学习

    这一周学习的还是面向对象的方法和应用 Java中方法的使用和注意事项 如果没有返回值,就不允许通过return关键字返回结果 方法中不允许嵌套使用 Return返回值只允许返回一个值,不允许返回多个 ...

  6. PDOstament对象执行execute()函数,只要是sql语句正确都是返回true

    [PDO对象操作数据库] PDOstament对象执行execute()函数,只要是sql语句正确都是返回true. 问题: 想要PDO对象实现更改一条记录, 并修改是否成功要返回信息给用户. 上我的 ...

  7. Android中的FrameLayout帧布局

    帧布局由FrameLayout所代表,FrameLayout直接继承了ViewGoup组件. 帧布局容器为每一个增加当中的组件创建一个空白的区域(称为一个帧),每一个子组件占领一帧,这些帧都会依据gr ...

  8. uvalive 2326 - Moving Tables(区间覆盖问题)

    题目连接:2326 - Moving Tables 题目大意:在一个走廊上有400个教室, 先在有一些桌子要移动, 每次移动需要十分钟, 但是不同房间的桌子可以在同一个十分钟内移动,只要走廊没有被占用 ...

  9. Tomcat7.0.40 基于DataSourceRealm的和JDBCRealm的资源用户访问控制

    软件版本: Tomcat 7.0.40 Mysql: 5.1 Host: CentOS 6.3 64bit 使用JDBCRealm (Tomcat 会使用所给的JDBC Connecter 自己去连M ...

  10. ARCGIS二维三维导航

    在使用代码前需要先安装arcgis10.0    或者10.1都可以    不过本人建议初学者安装10.0比较容易安装.. 安装方式和二维三维地图的加载网上都有,就不在此一一赘述了. 先从基本的功能开 ...