文章目录
一、onDraw 和 onDrawOver 绘制要点
二、onDraw 方法示例
三、onDrawOver 方法示例
四、完整代码示例
五、RecyclerView 相关资料
一、onDraw 和 onDrawOver 绘制要点
onDraw 和 onDrawOver 方法原理类似 , 都是基于 Canvas 进行绘制 , 这个 Canvas 的画布大小与 RecyclerView 大小相同 , 这里要注意 , 每一次绘制时 , 都要先获取要绘制的 item 组件对应的坐标 ;
这里的用法与 getItemOffsets 完全不同 , 设置每个元素的边距偏移时 , 可以获取当前的序号 , 并针对不同的序号代表的 item 条目进行不同的边距设置 ;
Canvas 中绘图的坐标系的 ( 0, 0 ) 位置是 RecyclerView 的左上角位置 ;
使用 Canvas 绘图时 , 先获取指定组件 , 然后获取该组件相对于父容器 ( RecyclerView ) 的坐标 ;
绘图的流程 :
① 获取组件个数 ;
② 遍历组件 ;
③ 获取组件 View 对象 ;
④ 获取组件 View 对象相对于父容器 RecyclerView 的坐标值 , 也就是左上右下四个坐标 ;
⑤ 根据获取的坐标值进行绘图 ;
绘图代码示例 : 以 onDraw 方法为例 , onDrawOver 的绘图逻辑类似 ;
@Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { // 1. 获取当前的组件个数 int itemCount = parent.getChildCount(); // 2. 遍历当前的所有组件 for (int i = 0; i < itemCount; i++) { // 3. 获取组件 View 对象 View view = parent.getChildAt(i); // 4. 获取 item 组件相对于父容器的坐标 int left = view.getLeft(); int top = view.getTop(); int right = view.getRight(); int bottom = view.getBottom(); // 5. 根据上述坐标进行绘图 c.draw... } }
二、onDraw 方法示例
这里给出一个需求 , 为每一行的第一个元素 , 添加红色矩形背景 , 范围是每隔 item 向外延展 5 55 像素 ;
代码示例 :
@Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { // 1. 获取当前的组件个数 int itemCount = parent.getChildCount(); // 2. 遍历当前的所有组件 for (int i = 0; i < itemCount; i++) { // 3. 获取组件 View 对象 View view = parent.getChildAt(i); // 4. 获取 item 组件相对于父容器的坐标 int left = view.getLeft(); int top = view.getTop(); int right = view.getRight(); int bottom = view.getBottom(); // 5. 根据上述坐标进行绘图 if (i % 4 == 0){ // 给每一行的第一个元素绘制红色矩形背景, 向外延展 5 像素 Paint paint = new Paint(); paint.setColor(Color.RED); c.drawRect(left - 5, top - 5, right + 5, bottom + 5, paint); } } }
运行效果 : 绘制的矩形被 item 组件元素覆盖了 , 因此只显示出外层的一圈边框 ;
三、onDrawOver 方法示例
给每个 item 条目设置上绘制一个遮罩 , 偶数序号的元素绘制蓝色圆形遮罩 , 奇数序号的元素上绘制红色矩形遮罩 ;
@Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { // 1. 获取当前的组件个数 int itemCount = parent.getChildCount(); // 2. 遍历当前的所有组件 for (int i = 0; i < itemCount; i++) { // 3. 获取组件 View 对象 View view = parent.getChildAt(i); // 4. 获取 item 组件相对于父容器的坐标 int left = view.getLeft(); int top = view.getTop(); int right = view.getRight(); int bottom = view.getBottom(); // 5. 根据上述坐标进行绘图 if (i % 2 == 0){ // 偶数序号的元素绘制蓝色圆形遮罩 Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5F); c.drawCircle((left + right) / 2F, (top + bottom) / 2F, (right - left) / 4F, paint); }else{ // 奇数序号的元素绘制红色矩形遮罩 Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5F); c.drawRect(left + 20, top + 20, right - 20, bottom - 20, paint); } } }
运行效果 : 偶数序号的元素绘制蓝色圆形遮罩 , 奇数序号的元素上绘制红色矩形遮罩 ; 该方法中绘制的元素覆盖 item 组件元素 ;