RecyclerView的分割線是通過畫布和設置項目偏移量來繪制的。妳需要知道兩種方法。
GetItemOffsets()和onDraw方法
GetItemOffsets用於每個ItemView。
OnDraw:遍歷並修改顏色。
我們可以看到,用戶定義的TestDividerItemDeoration只實現了壹個方法,getItemOffsets()。該方法中有四個參數。
直接出口
視圖視圖
RecyclerView父級
RecyclerView。狀態狀態
綠色區域代表RecyclerView中的壹個ItemView,外面橙色區域是對應的outRect,即ItemView與其他組件之間的偏移區域,相當於margin屬性。通過覆蓋getItemOffsets()方法,然後在outRect中指定top、left、right和bottom,可以控制所有方向的間隔。
這樣就實現了簡單的分隔線效果,但是這種方法的效果只能依賴於背景顏色。如果我想自定義分隔線的顏色怎麽辦?此時需要OnDraw()。
————————————————
源代碼分析:在recycleview中
註意分割線,沒有顏色,默認是白色,會看不見。
第壹個方案,通過
GetItemOffsets()方法來分割線!
判斷是第壹個還是最後壹個,是單人還是雙人,是什麽類型。
/***
*註意分割線,沒有顏色,默認是白色,不會看出來。
* @param outRect
* @param視圖
* @param parent
* @param狀態
*/
private void testitem offset(Rect outRect,View view,RecyclerView parent,RecyclerView。State state) {
int childAdapterPosition = parent . getchildadapterposition(view);
if (childAdapterPosition ==0) {
outRect.set(0,20,0,20);
}否則{
outRect.set(0,0,0,20);
}
}
第二個方案:ondraw()
@覆蓋
public void onDraw(Canvas c,RecyclerView parent,RecyclerView。State state) {
super.onDraw(c,parent,state);
int child count = parent . get child count();
for(int I = 0;我& lt兒童計數;i++) {
view view = parent . get child at(I);
int index = parent . getchildadapterposition(視圖);
//不需要繪制第壹個ItemView。
if (index ==0) {
繼續;
}
float divider top = view . gettop()-mDividerHeight;
float divider left = parent . getpadding left();
float divider bottom = view . gettop();
float divider right = parent . getwidth()-parent . getpadding right();
c.drawRect(dividerLeft、dividerTop、dividerRight、dividerBottom、MP aint);
}
}
?GridLayoutManager布局項的左右間距相等。
思維分析
首先我們知道,對於GridLayoutmanager,當我們將spancount設置為3時,那麽每壹項的最大寬度為item maxw = recycle rw/span count = recycle w3。
假設我們的spancount是3,那麽在沒有設置itemdata的情況下,它的分布是這樣的。您可以看到第壹列和最後壹行之間的距離不同。
GridVIew的問題:item的高度和寬度最初是固定的。
1.分割線是存在的,並不理想,左右相當。
2.沒有上下之分。
源代碼是這樣獲得的:
根據上面分析的源代碼,我們可以知道,當我們調用Outrect的方法時。Set (int left,int top,int right,int bottom),左邊永遠是0,右邊永遠是分割線的寬度,每壹項的寬度減去(left+right)的大小。
左始終為0,右始終為分隔線的寬度。
左上右下的值是多少?
計算每壹項的移動距離,左右移動距離。
計算分析:
1.左分割線的寬度為sW(已知)。
2.每個顯示項目的寬度和由布局定義的項目寬度。
3.總分隔線寬度:totalDivider=屏幕寬度-spanCount*itemWidth
4.列間分隔線的寬度為dw =(屏幕寬度-spanCount*item-2*sW?)/(spantcount-1)
5.每壹項需要留多少空間?Ew=totalDivider/spanCount(即paddingLeft+paddingRight)。
左:?左間距值(絕對值、差值)
Right:右側的間距值。
每個項目移動的距離:
第壹項:l0 = SW?R0=eW-sW
第二項:l 1 = dw-r0 = dw-ew+SWR 1 = ew-l 1 = 2ew-dw-SW。
第三項:L2 = dw-r 1 = 2(dw-ew)+SWR 2 = ew-L2 = 3ew-2dw-SW。
獲取公式:
Ln=(位置%跨度)*(dw-ew)+sw
Rn=ew-Ln
總結:得出三個值dw,ew,SW。
斯蒂芬尼.懷特:向左的距離
Ew:各自的平均分割線。
Dw:列間分隔線的寬度
int firstLastSpace = 50//最左邊分隔線的寬度
@SuppressLint("LongLogTag ")
@覆蓋
public void getitem offsets(Rect outRect,View view,RecyclerView parent,RecyclerView。State state) {
super.getItemOffsets(outRect,view,parent,state);
count++;
outRect.top = 20
mDividerHeight = 0;
int itemWidth =dip2px(context,100);
int screen width = getScreenWidth(context);
int dw =(screen width-3 * item width-2 * first last space)/2;//最後計算這個填充值。
//誤區:中間分割線的總距離從左到右可能不相等。
int totalDivder = screen width-3 * item width;
log . d(" TestDividerItemDecoration "," total divider "+total divider);
int eachDivder = total divder/3;
int item position =((recycle view。layout params)view . getlayout params())。getViewLayoutPosition();
//不要使用for循環。
out rect . left =(item position % 3)*(dw-eachDivder)+first last space;
outrect . right = eachDivder-outrect . right;
}
錯誤的想法:
//誤區:中間分割線的總距離從左到右可能不相等。
//不要使用for循環。
int firstLastSpace = 50//最左邊分隔線的寬度
@SuppressLint("LongLogTag ")
@覆蓋
public void getitem offsets(Rect outRect,View view,RecyclerView parent,RecyclerView。State state) {
super.getItemOffsets(outRect,view,parent,state);
count++;
outRect.top = 20
mDividerHeight = 0;
int itemWidth =dip2px(context,100);
int screen width = getScreenWidth(context);
int padding =(screen width-3 * item width-2 * first last space)/4;//最後計算這個填充值。
//妳不能這麽做。妳必須保證每壹項的分割線都是壹樣的。
log . d(" testdivideitemdecotion "," GetItemOffsets"+Count+"項目寬度:"+Item Width+" padding "+padding);
//只計算左右的距離。
int child count = parent . get child count();
for(int I = 0;我& lt兒童計數;i++) {
If (i %3 ==0) {//最左邊的項目
out rect . left = first last space;
outRect.right =填充;
}else if (i %3 ==1) {
outRect.left =填充;
outRect.right =填充;
}else if (i %3 ==2) {
outRect.left =填充;
out rect . right = first last space;
}
}
}
瀑布流的設置:
int span index = layout params . getspan index();
公共類feeddorationextends recycler view。項目裝飾{
私有homepagecardaptermhomepagecardapter;
公共feed decoration(homepagecardapter mhomepagecardapter){
this . mhomepagecardapter = mhomepagecardapter;
}
@覆蓋
public void getitem offsets(@ NonNull Rect outRect,@NonNull View view,@ NonNull RecyclerView parent,@ NonNull recycle View。State state) {
if(mhomepagecardapter = = null){
返回;
}
if(mhomepagecardapter . getitemviewtype(parent . getchildadapterposition(view))= = HomePageMultipleCard。home page _ MULTIPLE _ CARD _ TYPE _ FITNESS _ FEED){
StaggeredGridLayoutManager。layout params layout params =(StaggeredGridLayoutManager。layout params)view . getlayout params();
int span index = layout params . getspan index();
if (spanIndex ==0) {
out rect . set(density util . dip 2 px(shadow app . context(),14),0,density util . dip 2 px(shadow app . context(),5),density util . dip 2 px(shadow app . context(),10));
}否則{
out rect . set(density util . dip 2 px(shadow app . context(),5),0,density util . dip 2 px(shadow app . context(),14),density util . dip 2 px(shadow app . context(),10));
}
}
}
}
演示地址:/Peng Cai Hua 123456/深南大道