RecycleView的ItemDecoration的源码分析及调用原理

前言

ItemDecoration是实现了在RecyclerView对Item控件的绘制操作,因为以前研究PickView源码的时候,它是基于View的onDraw来绘制的,当时我就想着怎么实现,在ViewGroup中去执行这个onDraw,来绘制一些布局,感觉这个给了我一些思路,因此分析了一下源码,记录一下。

不仅如此,这里还对接口的的使用,算是一种静态代理模式,自己也想模拟这种的使用方法,把一个固定的父类的绘制,再辅助以子类灵活的绘制,这种代码的模式,觉得让自己受益非浅,感觉它不同于适配者模式,也不是策略模式,希望以后在工作中把这种模式灵活的运用下来。

源码部分

一、初始化

final ArrayList<RecyclerView.ItemDecoration> mItemDecorations;

//初始化

this.mItemDecorations = new ArrayList();

二、添加和删除

//添加

 public void addItemDecoration(@NonNull RecyclerView.ItemDecoration decor, int index) {
        if (this.mLayout != null) {
            this.mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll  or layout");
        }

        if (this.mItemDecorations.isEmpty()) {
            this.setWillNotDraw(false);
        }

        if (index < 0) {
            this.mItemDecorations.add(decor);
        } else {
            this.mItemDecorations.add(index, decor);
        }

        this.markItemDecorInsetsDirty();
        this.requestLayout();
    }

//删除

    public void removeItemDecorationAt(int index) {
        int size = this.getItemDecorationCount();
        if (index >= 0 && index < size) {
            //getItemDecorationAt 获取单个
            this.removeItemDecoration(this.getItemDecorationAt(index));
        } else {
            throw new IndexOutOfBoundsException(index + " is an invalid index for size " + size);
        }
    }

public void removeItemDecoration(@NonNull RecyclerView.ItemDecoration decor) {
        if (this.mLayout != null) {
            this.mLayout.assertNotInLayoutOrScroll("Cannot remove item decoration during a scroll  or layout");
        }

        this.mItemDecorations.remove(decor);
        if (this.mItemDecorations.isEmpty()) {
            this.setWillNotDraw(this.getOverScrollMode() == 2);
        }

        this.markItemDecorInsetsDirty();
        this.requestLayout();
    }

三、获取

    @NonNull
    public RecyclerView.ItemDecoration getItemDecorationAt(int index) {
        int size = this.getItemDecorationCount();
        if (index >= 0 && index < size) {
            return (RecyclerView.ItemDecoration)this.mItemDecorations.get(index);
        } else {
            throw new IndexOutOfBoundsException(index + " is an invalid index for size " + size);
        }
    }

    public int getItemDecorationCount() {
        return this.mItemDecorations.size();
    }

四、绘制,这个是ItemDecoration的重点

调用顺序,这里是分三层绘制的。

第一层:

在RecyclerView的onDraw中调用onDraw,实现接口子控件的绘制,经常会看到这种用法,静态代理模式,这里也是实现了对ViewGroup方法的绘制的补充,ViewGroup我们知道是直接修改的布局,对onDraw的运用几乎没有,这里确有使用。

在这里【onDraw】是在RecyclerView的【onDraw】中调用的,是不同于ItemDecoration的【onDrawOver】方法的,它是绘制的会被RecyclerView的子View遮挡的,因为最先绘制,所以在最下方。

   public void onDraw(Canvas c) {
        super.onDraw(c);
        int count = this.mItemDecorations.size();

        for(int i = 0; i < count; ++i) {
            ((RecyclerView.ItemDecoration)this.mItemDecorations.get(i)).onDraw(c, this, this.mState);
        }

    }

第二层:

绘制RecyclerView的子控件

第三层:在RecycleView的【draw】方法中调用这个方法,实现了代理模式,在ViewGroup绘制时,实现了自定义控件的绘制,其中【onDrawOver】绘制的是不会被覆盖的视图。因为最后绘制,所以在最上方。

        int count = this.mItemDecorations.size();

        for(int i = 0; i < count; ++i) {
            ((RecyclerView.ItemDecoration)this.mItemDecorations.get(i)).onDrawOver(c, this, this.mState);
        }

这里面,可以看出onDraw和onDrawOver的区别,是绘制顺序的不同,所以造成显示的内容不同。

五、滚动绘制

在scrollByInternal中调用,scrollByInternal是在Recycleview滚动时调用的,滚动时需要刷新子控件的布局

        if (!this.mItemDecorations.isEmpty()) {
            this.invalidate();
        }

六、ViewFlinger子线程中绘制

     if (!RecyclerView.this.mItemDecorations.isEmpty()) {
                        RecyclerView.this.invalidate();
                    }

七、公共方法,强制刷新布局

    public void invalidateItemDecorations() {
        if (this.mItemDecorations.size() != 0) {
            if (this.mLayout != null) {
                this.mLayout.assertNotInLayoutOrScroll
("Cannot invalidate item decorations during a scroll or layout");
            }

            this.markItemDecorInsetsDirty();
            this.requestLayout();
        }
    }

参考:

View 的onDraw和Draw的区别: https://blog.csdn.net/qq_25711251/article/details/51655162

RecycyleView的Item的分析:https://blog.csdn.net/weixin_36709064/article/details/82078813

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android中,RecyclerView可以通过Adapter传递数据到ViewHolder,然后在ViewHolder中使用这些数据来更新视图。如果你想在RecyclerView中传递绝对路径,可以将路径作为字符串传递到适配器中,并在ViewHolder中使用该字符串来加载图像或其他资源。 例如,你可以在Adapter中创建一个List<String>,其中每个字符串代表一个文件的绝对路径。然后在ViewHolder中,可以使用这些路径来加载图像或其他资源。以下是一个简单的示例: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private List<String> mPaths; public MyAdapter(List<String> paths) { mPaths = paths; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item_layout, parent, false); MyViewHolder viewHolder = new MyViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { String path = mPaths.get(position); holder.bind(path); } @Override public int getItemCount() { return mPaths.size(); } public static class MyViewHolder extends RecyclerView.ViewHolder { private ImageView mImageView; public MyViewHolder(View itemView) { super(itemView); mImageView = itemView.findViewById(R.id.image_view); } public void bind(String path) { // 加载图像或其他资源 Bitmap bitmap = BitmapFactory.decodeFile(path); mImageView.setImageBitmap(bitmap); } } } ``` 这是一个简单的示例,你可以根据实际需求进行调整。注意,加载大量图像时,可能需要使用异步加载机制来避免阻塞UI线程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值