谷歌的官方介绍: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.
作用:specific item views,自定义recyclerView的item的样式,RecyclerView提供了addItemDecoration接口与ItemDecoration类用来定制分割线样式。
Api介绍
getItemOffSet():
-
谷歌:
Retrieve any offsets for the given item. Each field of outRect specifies the number of pixels that the item view should be inset by, similar to padding or margin. The default implementation sets the bounds of outRect to 0 and returns.If this ItemDecoration does not affect the positioning of item views, it should set all four fields of outRect (left, top, right, bottom) to zero before returning.
-
中文解释:
获取已经设置在item上的offset(开始位置),每一个outRect具体说明了对应item的被插入位置(单位px),如果我们自定义的这个ItemDecoration不想影响item相对于recyclerView的位置,应该将outRect的四个field(left, top, right, bottom)设置为0
onDraw():
-
谷歌:
Draw any appropriate decorations into the Canvas supplied to the RecyclerView. Any content drawn by this method will be drawn before the item views are drawn, and will thus appear underneath the views.
-
中文:
为item画自定义样式,这个样式会在item绘制前绘制。
Paint&Canvas
-
Paint 画笔 :设置画笔颜色,画笔粗细
paint = new Paint();
paint.setColor(Color.parseColor("#D8D8D8"));
paint.setStrokeWidth(2);
-
Canvas 画布 :设置view的位置,view的内容
canvas.drawBitmap(mIcon, iconCenterX, iconCenterY, paint);
参数分别是bitmap,x轴坐标,y轴坐标,画笔(相对于父view坐标)
canvas还有其他的绘制方法:
canvas.drawArc();
canvas.drawBitmap();
canvas.drawCircle();
canvas.drawLines();
canvas.drawOval();
示例
现在要做一个这样的RecyclerView,通过ItemDecoration去完成,
左边是在onDraw中画的一个bitmap和line,右边是原来的item,通过getgetItemOffSet方法,将item向右移动,腾出空白,在onDraw中画出。
自定义ItemDecoration
public class SuperviseItemDecoration extends RecyclerView.ItemDecoration {
// 设置item的偏移量
private int left_offset;
private int top_offset;
// 所画图标半径
private int bitmap_radius;
// 画笔
private Paint paint_bitmap;
private Paint paint_line;
// 图标资源
private Bitmap bitmap;
public SuperviseItemDecoration(Context context) {
left_offset = QMUIDisplayHelper.dpToPx(60);
top_offset = QMUIDisplayHelper.dpToPx(10);
bitmap_radius = QMUIDisplayHelper.dpToPx(5);
paint_bitmap = new Paint();
paint_line = new Paint();
paint_line.setColor(Color.BLACK);
paint_line.setStrokeWidth(2);
bitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_flow_success);
bitmap_radius = bitmap.getWidth()/2;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// 左偏移60dp,上偏移10dp
outRect.set(left_offset,top_offset,0,0);
}
@Override
public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(canvas, parent, state);
int childCount = parent.getChildCount();
// 循环draw
for (int i = 0 ; i<childCount ;i++){
// 获取当前item的坐标,用于计算此次循环draw的位置
View childView = parent.getChildAt(i);
int bitmap_x = childView.getLeft()/2-bitmap_radius;
int bitmap_y = childView.getTop();
// 画图标
canvas.drawBitmap(bitmap,bitmap_x,bitmap_y,paint_bitmap);
if (i == childCount-1){
// 最后一个item不画线
}else {
int line_start_x = childView.getLeft()/2;
int line_start_y = childView.getTop()+bitmap_radius*2;
int line_end_x = childView.getLeft()/2;
int line_end_y = childView.getBottom();
// 画线
canvas.drawLine(line_start_x,line_start_y,line_end_x,line_end_y,paint_line);
}
}
}
}
在ondraw中需要注意的是,canvas.draw方法执行一次,只有一个图像,如果不用循环每次动态的获取child的x,y坐标,那么所有的draw的东西都会重复在一个上。
应用到RecyclerView上
recyclerView.addItemDecoration(new SuperviseItemDecoration(getContext()));