【RecyclerView】 八、RecyclerView.ItemDecoration 条目装饰 ( onDraw 和 onDrawOver 绘制要点 )
文章目錄
- 一、onDraw 和 onDrawOver 繪制要點(diǎn)
- 二、onDraw 方法示例
- 三、onDrawOver 方法示例
- 四、完整代碼示例
- 五、RecyclerView 相關(guān)資料
一、onDraw 和 onDrawOver 繪制要點(diǎn)
onDraw 和 onDrawOver 方法原理類似 , 都是基于 Canvas 進(jìn)行繪制 , 這個(gè) Canvas 的畫布大小與 RecyclerView 大小相同 , 這里要注意 , 每一次繪制時(shí) , 都要先獲取要繪制的 item 組件對(duì)應(yīng)的坐標(biāo) ;
這里的用法與 getItemOffsets 完全不同 , 設(shè)置每個(gè)元素的邊距偏移時(shí) , 可以獲取當(dāng)前的序號(hào) , 并針對(duì)不同的序號(hào)代表的 item 條目進(jìn)行不同的邊距設(shè)置 ;
Canvas 中繪圖的坐標(biāo)系的 ( 0, 0 ) 位置是 RecyclerView 的左上角位置 ;
使用 Canvas 繪圖時(shí) , 先獲取指定組件 , 然后獲取該組件相對(duì)于父容器 ( RecyclerView ) 的坐標(biāo) ;
繪圖的流程 :
① 獲取組件個(gè)數(shù) ;
② 遍歷組件 ;
③ 獲取組件 View 對(duì)象 ;
④ 獲取組件 View 對(duì)象相對(duì)于父容器 RecyclerView 的坐標(biāo)值 , 也就是左上右下四個(gè)坐標(biāo) ;
⑤ 根據(jù)獲取的坐標(biāo)值進(jìn)行繪圖 ;
繪圖代碼示例 : 以 onDraw 方法為例 , onDrawOver 的繪圖邏輯類似 ;
@Overridepublic void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前的組件個(gè)數(shù)int itemCount = parent.getChildCount(); // 2. 遍歷當(dāng)前的所有組件 for (int i = 0; i < itemCount; i++) { // 3. 獲取組件 View 對(duì)象 View view = parent.getChildAt(i);// 4. 獲取 item 組件相對(duì)于父容器的坐標(biāo) int left = view.getLeft();int top = view.getTop(); int right = view.getRight(); int bottom = view.getBottom(); // 5. 根據(jù)上述坐標(biāo)進(jìn)行繪圖 c.draw...}}二、onDraw 方法示例
這里給出一個(gè)需求 , 為每一行的第一個(gè)元素 , 添加紅色矩形背景 , 范圍是每隔 item 向外延展 555 像素 ;
代碼示例 :
@Overridepublic void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,@NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前的組件個(gè)數(shù)int itemCount = parent.getChildCount();// 2. 遍歷當(dāng)前的所有組件for (int i = 0; i < itemCount; i++) {// 3. 獲取組件 View 對(duì)象View view = parent.getChildAt(i);// 4. 獲取 item 組件相對(duì)于父容器的坐標(biāo)int left = view.getLeft();int top = view.getTop();int right = view.getRight();int bottom = view.getBottom();// 5. 根據(jù)上述坐標(biāo)進(jìn)行繪圖if (i % 4 == 0){// 給每一行的第一個(gè)元素繪制紅色矩形背景, 向外延展 5 像素Paint paint = new Paint();paint.setColor(Color.RED);c.drawRect(left - 5, top - 5, right + 5, bottom + 5, paint);}}}運(yùn)行效果 : 繪制的矩形被 item 組件元素覆蓋了 , 因此只顯示出外層的一圈邊框 ;
三、onDrawOver 方法示例
給每個(gè) item 條目設(shè)置上繪制一個(gè)遮罩 , 偶數(shù)序號(hào)的元素繪制藍(lán)色圓形遮罩 , 奇數(shù)序號(hào)的元素上繪制紅色矩形遮罩 ;
@Overridepublic void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,@NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前的組件個(gè)數(shù)int itemCount = parent.getChildCount();// 2. 遍歷當(dāng)前的所有組件for (int i = 0; i < itemCount; i++) {// 3. 獲取組件 View 對(duì)象View view = parent.getChildAt(i);// 4. 獲取 item 組件相對(duì)于父容器的坐標(biāo)int left = view.getLeft();int top = view.getTop();int right = view.getRight();int bottom = view.getBottom();// 5. 根據(jù)上述坐標(biāo)進(jìn)行繪圖if (i % 2 == 0){// 偶數(shù)序號(hào)的元素繪制藍(lán)色圓形遮罩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{// 奇數(shù)序號(hào)的元素繪制紅色矩形遮罩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);}}}運(yùn)行效果 : 偶數(shù)序號(hào)的元素繪制藍(lán)色圓形遮罩 , 奇數(shù)序號(hào)的元素上繪制紅色矩形遮罩 ; 該方法中繪制的元素覆蓋 item 組件元素 ;
四、完整代碼示例
RecyclerView.ItemDecoration 代碼示例 :
package kim.hsl.recyclerview;import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.view.View;import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView;public class ItemDecoration extends RecyclerView.ItemDecoration {@Overridepublic void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,@NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前的組件個(gè)數(shù)int itemCount = parent.getChildCount();// 2. 遍歷當(dāng)前的所有組件for (int i = 0; i < itemCount; i++) {// 3. 獲取組件 View 對(duì)象View view = parent.getChildAt(i);// 4. 獲取 item 組件相對(duì)于父容器的坐標(biāo)int left = view.getLeft();int top = view.getTop();int right = view.getRight();int bottom = view.getBottom();// 5. 根據(jù)上述坐標(biāo)進(jìn)行繪圖if (i % 4 == 0){// 給每一行的第一個(gè)元素繪制紅色矩形背景, 向外延展 5 像素Paint paint = new Paint();paint.setColor(Color.RED);c.drawRect(left - 5, top - 5, right + 5, bottom + 5, paint);}}}@Overridepublic void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,@NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前的組件個(gè)數(shù)int itemCount = parent.getChildCount();// 2. 遍歷當(dāng)前的所有組件for (int i = 0; i < itemCount; i++) {// 3. 獲取組件 View 對(duì)象View view = parent.getChildAt(i);// 4. 獲取 item 組件相對(duì)于父容器的坐標(biāo)int left = view.getLeft();int top = view.getTop();int right = view.getRight();int bottom = view.getBottom();// 5. 根據(jù)上述坐標(biāo)進(jìn)行繪圖if (i % 2 == 0){// 偶數(shù)序號(hào)的元素繪制藍(lán)色圓形遮罩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{// 奇數(shù)序號(hào)的元素繪制紅色矩形遮罩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);}}}@Overridepublic void getItemOffsets(@NonNull Rect outRect, @NonNull View view,@NonNull RecyclerView parent,@NonNull RecyclerView.State state) {// 1. 獲取當(dāng)前設(shè)置邊距的位置int currentPosition = parent.getChildAdapterPosition(view);// 2. 針對(duì)不同的位置設(shè)置不同的邊距// 每排最左側(cè)和最右側(cè)的左右邊距設(shè)置成 20 像素, 其余 4 個(gè)邊距一律設(shè)置成 5if (currentPosition % 4 == 0){// 每排最左側(cè)的邊距outRect.left = 40;outRect.top = 20;outRect.right = 20;outRect.bottom = 20;}else if (currentPosition %4 == 3){// 每排最右側(cè)的邊距outRect.left = 20;outRect.top = 20;outRect.right = 40;outRect.bottom = 20;}else{// 普通元素的邊距都是 5outRect.left = 20;outRect.top = 20;outRect.right = 20;outRect.bottom = 20;}} }主界面代碼示例 :
package kim.hsl.recyclerview;import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//1 . 從布局中獲取 RecyclerViewRecyclerView recycler_view = findViewById(R.id.recycler_view);//2 . 創(chuàng)建并設(shè)置布局管理器//創(chuàng)建布局管理器StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(4,RecyclerView.VERTICAL);//設(shè)置布局管理器recycler_view.setLayoutManager(layoutManager);// 設(shè)置邊距recycler_view.addItemDecoration(new ItemDecoration());//3 . 創(chuàng)建并設(shè)置列表適配器Adapter adapter = new Adapter();recycler_view.setAdapter(adapter);}/*** RecyclerView 適配器*/public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View root_view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_recyclerview, parent, false);return new ViewHolder(root_view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {holder.text.setText("" + position);}@Overridepublic int getItemCount() {return 100;}public class ViewHolder extends RecyclerView.ViewHolder {TextView text;public ViewHolder(@NonNull View itemView) {super(itemView);text = itemView.findViewById(R.id.text);}}}}運(yùn)行效果 :
① 邊距 : 正常的 item 邊距設(shè)置都是 20 像素 , 每行最左側(cè)距離左邊 40 像素 , 每行最右側(cè)邊距距離右側(cè) 40 像素 ;
① item 底部背景 : 使用 onDraw 方法繪制 , 給每行的第一個(gè)元素繪制一個(gè)底部背景 , 該背景會(huì)被 item 組件覆蓋 ;
③ item 上層遮罩 : 使用 onDrawOver 方法繪制 , 給偶數(shù)序號(hào)的 item 元素繪制藍(lán)色圓形遮罩 , 給奇數(shù)序號(hào)的 item 元素繪制紅色矩形遮罩 ;
五、RecyclerView 相關(guān)資料
官方文檔 :
使用 RecyclerView 創(chuàng)建動(dòng)態(tài)列表 : https://developer.android.google.cn/guide/topics/ui/layout/recyclerview
高級(jí) RecyclerView 自定義 : https://developer.android.google.cn/guide/topics/ui/layout/recyclerview-custom
代碼示例 :
GitHub 源碼地址 : https://github.com/han1202012/001_RecyclerView
博客源碼快照 : https://download.csdn.net/download/han1202012/14951850
( 使用 Android Studio 打開 )
總結(jié)
以上是生活随笔為你收集整理的【RecyclerView】 八、RecyclerView.ItemDecoration 条目装饰 ( onDraw 和 onDrawOver 绘制要点 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【RecyclerView】 七、Rec
- 下一篇: 【RecyclerView】 九、为 R