在平時(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.
比對后發(fā)現(xiàn)每個itemView底部多出了30px的空間 乔遮,推測出來應(yīng)該是修改的外邊距扮超,所以些分割線的時(shí)候,一定要算出精準(zhǔn)的距離申眼,否則會影響到寫好的Ui效果瞒津。
另外可以測試一下 ,左右上下都修改的效果括尸。
outRect.set(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);
}
}
看效果
。
好到此穷娱,垂直方向的分割線已經(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);
}
}
效果
以上就是在橫向和縱向RecyclerView中添加分割線的做法取董,還可以寫一個標(biāo)識符棍苹,將縱向和橫向分割符封裝在同一個 ItemDecoration中,根據(jù)傳入的不同值茵汰,來顯示不同的效果枢里。