进击的RecyclerView入门二(来点小装饰?)

接着上一讲,我们看到我们的Demo可以正常的运行,并且能自动加载网络图片,那么为了后面观察的方便,我们取消这种自动加载的功能,使用两个按钮来代替,分别用来增加一个数据和减少一个数据。截图如下:

正在我自认为这样的布局已经很完美的时候,产品经理A走过来指着手机说,“这样的布局太单调,给我改炫酷屌炸天一点!!!”

既然老大这么说了,我也没办法只能照办了。

想到要修改布局我第一个想到的是修改每个Item的布局文件(虽然这里我们没有布局文件,纯java写的),但仔细一想这样改了每一个Item还不是一样。那有没有什么办法可以区别对待这些Item,让不同位置的他们表现的不一样呢?

答案是Yes,RecyclerView有这么一个子ItemDecoration类专门是用来处理这类问题的。

我们先来看一下ItemDecoration的官方介绍:

An ItemDecoration allows the application to add a special drawing and layout offset to specific item views from the adapter’s data set. This can be useful for drawing dividers between items, highlights, visual grouping boundaries and more.

All ItemDecorations are drawn in the order they were added, before the item views (in onDraw() and after the items (in onDrawOver(Canvas, RecyclerView, RecyclerView.State).

简单理解就是ItemDecoration可以给指定的Item绘制指定的内容和添加偏移量。其中OnDraw发生在Item绘制前,OnDrawOver发生在Item绘制后。

了解完这些后我们就开始实战吧.

要做的很简单我们自定义一个ItemDecoration子类并重写它的如下方法即可:

1
2
3
4
5
6
7
8
//用于调整子View的偏移量
public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state)

//在子View绘制前绘制
onDraw (Canvas c, RecyclerView parent, RecyclerView.State state)

//在子View绘制后绘制
onDrawOver (Canvas c, RecyclerView parent, RecyclerView.State state)

我们重写子类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private class MyItemDecoration extends RecyclerView.ItemDecoration{

Paint paint = new Paint();

public MyItemDecoration(){
//初始化画笔
paint.setStyle(Paint.Style.STROKE);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {

}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
//在子View绘制后绘制
//我们布局是每行三个Item,当绘制到中间Item的时候,给他包裹一个相框,虽然我们的相框很挫。。。
for(int i = 0 ; i<parent.getChildCount();i++){
if( (i-1)%3 == 0 ){
View child = parent.getChildAt(i);
RecyclerView.LayoutParams rLP = (RecyclerView.LayoutParams) child.getLayoutParams();
int left = child.getLeft() ;
int top = child.getTop();
int right = child.getRight();
int bottom = child.getBottom() ;
c.drawRect(left,top,right,bottom,paint);
}
}
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//我们原始的布局所有的Item上下左右都有一个20像素的外边距
//这里我们修改成每行的第一个Item的左边距为0,每行第三个Item的右边距为0.
int position = parent.getChildAdapterPosition(view);
if( (position + 1)%3==0 ){
outRect.set(0,0,-20,0);
}
if(position % 3 == 0){
outRect.set(-20,0,0,0);
}
}
}

最后将这个ItemDecoration追加到RecyclerView上:

1
2
final MyItemDecoration myItemDecoration = new MyItemDecoration();
recyclerView.addItemDecoration(myItemDecoration);

OK,现在让我们来看看前后布局的对比:

是不是发现了其中微妙的变化?产品经理A这下应该满意了吧?

demo完整源码地址:
https://github.com/ZhangQinglian/RecyclerViewAdvance

如文章对您有所帮助,可以请作者喝杯 🍵