RecyclerView 添加分割線

在平時(shí)開發(fā)中侮腹,一直沒有用到 Android提供的ItemDecoration來設(shè)置分割線,不太熟悉用法,基本都是寫在列表的ViewHolder里,后來翻了一下Google提供的這個ItemDecoration泻仙,感覺還是挺好用的,花點(diǎn)時(shí)間量没,記錄一下使用方法。

使用到ItemDecoration突想,基本步驟

1.編寫一個RecyclerView.ItemDecoration的子類殴蹄,
2.重寫getItemOffsets方法 和onDraw方法究抓。
3.為RecyclerView添加一個ItemDecoration。
其中重點(diǎn)是第二條重寫getItemOffsets和onDraw方法袭灯。

1.先來看getItemOffsets方法

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}

先簡單理解這個方法在itemview 上下左右偏移出多少的空間用來畫分割線刺下,等下看到具體效果就能明白。
這個偏移量怎么設(shè)置呢稽荧,就設(shè)置在第一個參數(shù)outRect里:
outRect.set(int left,int top,int right,int bottom);
這四個參數(shù)橘茉,分別代表了itmeview的 左,上姨丈,右畅卓,下的偏移量。
好了蟋恬,這個時(shí)候推想一下翁潘,一個垂直方向的RecyclerView如果想在每個itemView的底部添加一個分割線,是不是就可以利用getItemOffsets方法歼争,在itemView的底部偏移出一個空間來畫分割線?
想法有了拜马,可以試試,先在底部偏移出30px的空間沐绒。
先寫一個RecyclerView 俩莽,代碼如下

public class RecyClerViewLineActivity extends BaseActivity {
private RecyclerView mRecyclerView;
private NameAdapter mNameAdapter;
private LinearLayoutManager mLinearLayoutManager;
@Override
protected void initView() {
setContentView(R.layout.ac_recy);
mRecyclerView = (RecyclerView) findViewById(R.id.ac_recy_list_rcy);
mLinearLayoutManager = new LinearLayoutManager(this  );
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mNameAdapter = new NameAdapter(this);
mRecyclerView.setAdapter(mNameAdapter);
CustomItemDecoration  mItemDecoration=new CustomItemDecoration(this);
mRecyclerView.addItemDecoration(mItemDecoration);
}
}
public class CustomItemDecoration extends RecyclerView.ItemDecoration {
//利用系統(tǒng)屬性中的listDivider來添加
public static final int[] ATRRS = new int[]{
android.R.attr.listDivider
};
private Context mContext;
private Drawable mDivder;
public CustomItemDecoration(Context mContext) {
this.mContext = mContext;
final TypedArray ta = mContext.obtainStyledAttributes(ATRRS);
this.mDivder = ta.getDrawable(0);
ta.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//只在下面 偏移
outRect.set(0, 0, 0,30);
}
}

簡單的一個RecyclerView,每個itemView 有個TextView.

沒有分割線的運(yùn)行效果
底部偏移了30px的效果

比對后發(fā)現(xiàn)每個itemView底部多出了30px的空間 乔遮,推測出來應(yīng)該是修改的外邊距扮超,所以些分割線的時(shí)候,一定要算出精準(zhǔn)的距離申眼,否則會影響到寫好的Ui效果瞒津。
另外可以測試一下 ,左右上下都修改的效果括尸。

outRect.set(10,5,15,30);
修改的偏移量為10,5,15,30的效果

2.知道了getItemOffsets方法后巷蚪,看現(xiàn)在看一下onDraw方法

 @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state); 

    }

后面兩個參數(shù)先不看,只看第一個濒翻,很明顯是傳入一個畫布屁柏,需要我們來畫圖了。
接著剛才的需求有送,我們已經(jīng)在itemView的下方偏移出了一個30px的高度淌喻,需要畫一個20px的高度的分割線。
要畫圖雀摘,得有畫布和坐標(biāo)裸删,畫布是給我們了,坐標(biāo)需要我們算出來阵赠。
結(jié)合需求涯塔,發(fā)現(xiàn)
1)分割線的left 是一定的肌稻,都等于容器的paddingleft。
2)分割線的right也是一定的匕荸,都等于容器的width- 容器的paddingRigth爹谭。
只剩下top和bottom了。
3)top等于每個itemView的bottom+ 每個itemView的marginBottom(因?yàn)槭窃诘撞浚?br> 4)bottom等于 剛剛算出來的top+分割線自身的高度榛搔。
好了 诺凡,四個左邊都給了可以畫圖了。

@Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        //垂直的列表的分割線 践惑,左邊距是一樣的,這里減去 父容器才paddingLeft
        int left=parent.getPaddingLeft();
        //同樣腹泌,右邊也是一樣的
        int right=parent.getWidth()-parent.getPaddingRight();
        //獲取child的count
        int count=parent.getChildCount();
        //循環(huán) 獲得 top  和 bottom
        for(int i=0;i<count;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams lyp =(RecyclerView.LayoutParams)child.getLayoutParams();
            // 獲取 child 的底邊到父容器的距離,因?yàn)榉指罹€在itme的下面童本,所以這個距離就變成了分割線的距離父容器的 top
            int top=child.getBottom()+lyp.bottomMargin;
            //top再加分割線的高度真屯,等于bottom
            int bottom=top+ 20;  //這里個20是假設(shè)的
            mDivder.setBounds(left,top,right,bottom);
            mDivder.draw(c);
        }


    }

看效果

30px的偏移和20px的分割線

好到此穷娱,垂直方向的分割線已經(jīng)完成了绑蔫。

3.其實(shí)根據(jù)剛才的推測,橫向的RecyclerView的分割線原理也很好推測泵额。(還是以右邊偏移30px配深,分割線20px為列)

1)首先是偏移方向,需要再itemView的右邊 偏移個30px的空間嫁盲。
2)分割線的top 是一定的篓叶,都等于容器的paddingTop。
3)分割線的bottom也是一定的羞秤,都等于容器的height- 容器的paddingBottom缸托。
只剩下right和left了。
4)left等于每個itemView的right+ 每個itemView的marginRight(因?yàn)槭窃谟疫叄?br> 5)right等于 剛剛算出來的left+分割線自身的寬度瘾蛋。

 @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

            //只在右邊 偏移
            outRect.set(0, 0, 30,0);

    }

//在onDraw里調(diào)用
 private void drawHorizontal(Canvas c, RecyclerView parent) {
        //水平的列表的分割線 俐镐,top是一定的
        int top=parent.getPaddingTop();
        //同樣,bottom也是一定的
        int bottom=parent.getHeight()-parent.getPaddingBottom();

        //獲取child的count
        int count=parent.getChildCount();
        //循環(huán) 獲得 left  和 right
        for(int i=0;i<count;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams lyp =(RecyclerView.LayoutParams)child.getLayoutParams();
            // 獲取 child 的右邊到父容器的距離哺哼,因?yàn)榉指罹€在itme的右邊佩抹,所以這個距離就變成了分割線的距離父容器的 left
            int left=child.getRight()+lyp.rightMargin;
            //left再加分割線的寬度,等于right
            int right=left+ 20px;
            mDivder.setBounds(left,top,right,bottom);
            mDivder.draw(c);
        }



    }

效果

橫向偏移30分割線20

以上就是在橫向和縱向RecyclerView中添加分割線的做法取董,還可以寫一個標(biāo)識符棍苹,將縱向和橫向分割符封裝在同一個 ItemDecoration中,根據(jù)傳入的不同值茵汰,來顯示不同的效果枢里。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坡垫,更是在濱河造成了極大的恐慌梭灿,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冰悠,死亡現(xiàn)場離奇詭異,居然都是意外死亡配乱,警方通過查閱死者的電腦和手機(jī)溉卓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搬泥,“玉大人桑寨,你說我怎么就攤上這事》揲荩” “怎么了尉尾?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長燥透。 經(jīng)常有香客問我沙咏,道長,這世上最難降的妖魔是什么班套? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任肢藐,我火速辦了婚禮,結(jié)果婚禮上吱韭,老公的妹妹穿的比我還像新娘吆豹。我一直安慰自己,他們只是感情好理盆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布痘煤。 她就那樣靜靜地躺著,像睡著了一般猿规。 火紅的嫁衣襯著肌膚如雪衷快。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天坎拐,我揣著相機(jī)與錄音烦磁,去河邊找鬼。 笑死哼勇,一個胖子當(dāng)著我的面吹牛都伪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播积担,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼陨晶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起先誉,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤湿刽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后褐耳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诈闺,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年铃芦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雅镊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡刃滓,死狀恐怖仁烹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咧虎,我是刑警寧澤卓缰,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站砰诵,受9級特大地震影響征唬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胧砰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一鳍鸵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尉间,春花似錦偿乖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至眠副,卻和暖如春画切,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背囱怕。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工霍弹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娃弓。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓典格,卻偏偏與公主長得像,于是被迫代替她去往敵國和親台丛。 傳聞我的和親對象是個殘疾皇子耍缴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評論 2 361

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