如何自定義RecycleView item的間距


引言

在以前使用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/.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM