Recyclerview GridLayout分隔間距

RecyclerView 支持網(wǎng)格布局滤淳,我們使用GridLayoutManager來設(shè)置為網(wǎng)格布局贤徒,在使用網(wǎng)格布局時(shí)遇到Item之間間隔的問題醉蚁,以下以每行三個(gè)為例來講解睛琳。
每行顯示三個(gè)圖片盒蟆,設(shè)置圖片寬度恒定(eg :100dp)后踏烙,在不設(shè)置分隔的情況下,recyclerview會(huì)自動(dòng)計(jì)算空隙寬度历等,然后填充到每個(gè)Item右邊讨惩,如下圖所示。但這種布局往往不滿足我們的使用習(xí)慣寒屯,我們一般需要使圖片左右靠邊荐捻,中間間隙自動(dòng)填充,因此我們需要移動(dòng)item的位置浩螺。如下所示靴患,需要將第二個(gè)、第三個(gè)Item右移要出。


gridLayout divider.png

下面開始介紹我們的實(shí)現(xiàn)方案鸳君,我們所需的工作就是計(jì)算每個(gè)item所需的移動(dòng)距離,計(jì)算的過程后面介紹患蹂,現(xiàn)在假設(shè)我們已經(jīng)計(jì)算出這個(gè)距離或颊,為dividerWidth,那么我們只需要以下代碼就ok了传于。

 private final int SPAN_COUNT = 3;
 gridLayoutManager = new GridLayoutManager(this, SPAN_COUNT, LinearLayoutManager.VERTICAL, false);
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                 return SPAN_COUNT/3;
            }
        })囱挑;
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    GridLayoutManager.LayoutParamslayoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
    int spanSize =layoutParams.getSpanSize();
    if(spanSize ==eachItemCount){
        int spanIndex =layoutParams.getSpanIndex();
        int itemPosition =spanIndex/eachItemCount;//eachItemCount每個(gè)item所占空間
        outRect.left =dividerWidth*itemPosition;//dividerWidth每份間隔寬度(item左側(cè)間距)下面會(huì)具體介紹.
    }
     outRect.bottom =dividerHeight;//item底部間距
}

設(shè)置完以上代碼就可以正常工作了,下面簡單介紹下他是怎么工作的:
outRect結(jié)構(gòu)如下所示沼溜,及矩形的數(shù)據(jù)結(jié)構(gòu)平挑,四個(gè)值分別代表目標(biāo)Item四周的距離,如下圖所示:

public final class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;}
Untitled Diagram (1).png

跟下源碼定位到以下代碼(版本V7-25.0.1):

 Rect getItemDecorInsetsForChild(View child) {
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        ...
        final Rect insets = lp.mDecorInsets;
        insets.set(0, 0, 0, 0);
        final int decorCount = mItemDecorations.size();//mItemDecorations為分割線的集合系草,因此GridLayout可以設(shè)置多個(gè)分隔線
        for (int i = 0; i < decorCount; i++) {
            mTempRect.set(0, 0, 0, 0);
           //此處調(diào)用我們重寫的函數(shù)通熄,insets是Item的四周間距,此處加上我們設(shè)置的間距
            mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState);
            insets.left += mTempRect.left;
            insets.top += mTempRect.top;
            insets.right += mTempRect.right;
            insets.bottom += mTempRect.bottom;
        }
        lp.mInsetsDirty = false;
        return insets;
    }

其實(shí)寫這篇文章的主要原因是Item移動(dòng)位置的計(jì)算找都,以下以每行三個(gè)為例計(jì)算每個(gè)item移動(dòng)的位置:


gridLayout divider (1).png

上圖中空白處和為1唇辨,則每個(gè)空白為1/3,移動(dòng)后一共兩個(gè)空白能耻,故每個(gè)占1/2赏枚,
顯然第二個(gè)Item需要右移(1/2-1/3 = 1/6)的位置,那么第三個(gè)item需要移動(dòng)自己的1/6距離+第二個(gè)item移動(dòng)的位置1/6晓猛,即2/6饿幅。因此我們在計(jì)算空白的寬度時(shí)將其分為6份。

  @Px int eachDividerWidth = (UISizeUtils.getScreenWidth(this)-UISizeUtils.dip2px(this,100)*SPAN_COUNT)/6;//把空白分為6份
        DividerGridLayout dividerGridLayout = new DividerGridLayout(1,eachDividerWidth,UISizeUtils.dip2px(this,10));

因此計(jì)算出每份距離后戒职,在getItemOffsets方法中根據(jù)spanIndex來計(jì)算每個(gè)Item距離左側(cè)的距離
outRect.left的距離栗恩,為dividerWidth*itemPosition。

 if(spanSize ==eachItemCount){
        int spanIndex =layoutParams.getSpanIndex();
        int itemPosition =spanIndex/eachItemCount;//eachItemCount每個(gè)item所占空間
        outRect.left =dividerWidth*itemPosition;//dividerWidth每份間隔寬度(item左側(cè)間距)
    }

將其推廣到每行四個(gè)Item時(shí)帕涌,每個(gè)每個(gè)空白為1/4摄凡,移動(dòng)后每個(gè)空白占1/3,因此每個(gè)Item需要移動(dòng)(1/3-1/4 = 1/12),每行5個(gè)Item時(shí)每個(gè)移動(dòng)(1/4-1/5 = 1/20)蚓曼,歸納總結(jié)亲澡。對于每行N個(gè)Item,每個(gè)Item需要移動(dòng)(1/(N*(N-1)))的位置纫版。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末床绪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子其弊,更是在濱河造成了極大的恐慌癞己,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梭伐,死亡現(xiàn)場離奇詭異痹雅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)糊识,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門绩社,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赂苗,你說我怎么就攤上這事愉耙。” “怎么了拌滋?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵朴沿,是天一觀的道長。 經(jīng)常有香客問我败砂,道長赌渣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任吠卷,我火速辦了婚禮锡垄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祭隔。我一直安慰自己货岭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布疾渴。 她就那樣靜靜地躺著千贯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搞坝。 梳的紋絲不亂的頭發(fā)上搔谴,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機(jī)與錄音桩撮,去河邊找鬼敦第。 笑死峰弹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的芜果。 我是一名探鬼主播鞠呈,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼右钾!你這毒婦竟也來了蚁吝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤舀射,失蹤者是張志新(化名)和其女友劉穎窘茁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脆烟,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡山林,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浩淘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌朴。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖张抄,靈堂內(nèi)的尸體忽然破棺而出砂蔽,到底是詐尸還是另有隱情,我是刑警寧澤署惯,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布左驾,位于F島的核電站,受9級特大地震影響极谊,放射性物質(zhì)發(fā)生泄漏诡右。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一轻猖、第九天 我趴在偏房一處隱蔽的房頂上張望帆吻。 院中可真熱鬧,春花似錦咙边、人聲如沸猜煮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽王带。三九已至,卻和暖如春市殷,著一層夾襖步出監(jiān)牢的瞬間愕撰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搞挣,地道東北人带迟。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像囱桨,于是被迫代替她去往敵國和親邮旷。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容