引言
在以前使用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為自然數) 。
-
$ x_{i}+ y_{i}=d (1<=i<=n,i為自然數,d為未知正數)$
-
\(y_{i}+x_{i+1}=D(1<i<=n)\)
-
\(x_{1}=D, y_{1}=D\)
其中需要說明的是,由於每個item的原始寬度一致,要使得每個item的左右邊距在空出相應距離后仍寬度一致,則公式1一定成立,具體示意圖如下:
由圖可知,自然的我們可以很快的找到一個等式①,即:
而由公式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/.