前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >可展开Recyclerview适配器支持Header、Footer、Empty、LoadMore

可展开Recyclerview适配器支持Header、Footer、Empty、LoadMore

作者头像
jerrypxiao
发布2021-02-22 11:07:37
7050
发布2021-02-22 11:07:37
举报
文章被收录于专栏:音视频专栏音视频专栏

前言

Android RecyclerView的适配器。面对各种列表的需求,急需要梳理一下,抽象出一个快速开发列表的适配器,减小代码量,提高开发效率。 可展开的Adapter支持的功能如下:

  • 支持两行可展开能力(单一类型适配)
  • 支持空状态;
  • 支持Header、Footer的适配
  • LoadMore的适配

使用类:BaseExpandableRecyclerViewAdapter demo地址:

1. 用法

(1)基本可展开的group写法

  • a 新增 父SampleGroupBean和子SampleChildBean
  • b 定义对应的父ViewHolder和子ViewHolder
  • c 实现adapter中对应的onCreateGroupViewHolder和onCreateChildViewHolder、onBindGroupViewHolder和onBindChildViewHolder
代码语言:javascript
复制
public class SampleAdapter extends
        BaseExpandableRecyclerViewAdapter<SampleGroupBean, SampleChildBean, SampleAdapter.GroupVH, SampleAdapter.ChildVH> {

    private List<SampleGroupBean> mList;

    public SampleAdapter(List<SampleGroupBean> list) {
        mList = list;
    }

    @Override
    public int getGroupCount() {
        return mList.size();
    }

    @Override
    public SampleGroupBean getGroupItem(int position) {
        return mList.get(position);
    }

    @Override
    public GroupVH onCreateGroupViewHolder(ViewGroup parent, int groupViewType) {
        return new GroupVH(
                LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.listitem_group, parent, false));
    }

    @Override
    public ChildVH onCreateChildViewHolder(ViewGroup parent, int childViewType) {
        return new ChildVH(
                LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.listitem_child, parent, false));
    }

    @Override
    public void onBindGroupViewHolder(GroupVH holder, SampleGroupBean sampleGroupBean, boolean isExpanding) {
        holder.nameTv.setText(sampleGroupBean.getName());
        if (sampleGroupBean.isExpandable()) {
            holder.foldIv.setVisibility(View.VISIBLE);
            holder.foldIv.setImageResource(isExpanding ? R.drawable.ic_arrow_expanding : R.drawable.ic_arrow_folding);
        } else {
            holder.foldIv.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void onBindChildViewHolder(ChildVH holder, SampleGroupBean groupBean, SampleChildBean sampleChildBean) {
        holder.nameTv.setText(sampleChildBean.getName());
    }

    static class GroupVH extends BaseExpandableRecyclerViewAdapter.BaseGroupViewHolder {
        ImageView foldIv;
        TextView nameTv;

        GroupVH(View itemView) {
            super(itemView);
            foldIv = (ImageView) itemView.findViewById(R.id.group_item_indicator);
            nameTv = (TextView) itemView.findViewById(R.id.group_item_name);
        }

        @Override
        protected void onExpandStatusChanged(RecyclerView.Adapter relatedAdapter, boolean isExpanding) {
            foldIv.setImageResource(isExpanding ? R.drawable.ic_arrow_expanding : R.drawable.ic_arrow_folding);
        }
    }

    static class ChildVH extends RecyclerView.ViewHolder {
        TextView nameTv;

        ChildVH(View itemView) {
            super(itemView);
            nameTv = (TextView) itemView.findViewById(R.id.child_item_name);
        }
    }

}

(2)支持Header、Footer写法

代码语言:javascript
复制
      adapter.setHeaderViewProducer(new ViewProducer() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new DefaultEmptyViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false)
                );
            }
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder) {
            }
        });
        adapter.setFooterViewProducer(new ViewProducer() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new DefaultEmptyViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_footview, parent, false)
                );
            }

            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder) {
            }
        });

(3)支持EmptyView写法

代码语言:javascript
复制
      adapter.setEmptyViewProducer(new ViewProducer() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new DefaultEmptyViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.empty, parent, false)
                );
            }
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder) {
            }
        });

(4)支持LoadMore写法

代码语言:javascript
复制
       adapter.setLoadMoreProducer(new ViewProducer() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new DefaultEmptyViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.load_next_page, parent, false)
                );
            }
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder) {
            }
        });

(5)点击的监听

代码语言:javascript
复制
            adapter.setListener(new BaseExpandableRecyclerViewAdapter.ExpandableRecyclerViewOnClickListener<GroupBean,
                    SampleChildBean>() {
                @Override
                public boolean onGroupLongClicked(GroupBean groupItem) {
                    return false;
                }
                @Override
                public boolean onInterceptGroupExpandEvent(GroupBean groupItem, boolean isExpand) {
                    return false;
                }
                @Override
                public void onGroupClicked(GroupBean groupItem) {
                }
                @Override
                public void onChildClicked(GroupBean groupItem, SampleChildBean childItem) {
              }
            });

2. 基本原理

基本继承RecyclerView.Adapter复写的类中封装了一些常用到的写法,抽象出来

(1)在getItemViewType中分别对ViewType做区分:VIEW_TYPE_EMPTY > VIEW_TYPE_LOADMORE > VIEW_TYPE_FOOT > VIEW_TYPE_HEAD。其中将Group和Child也当作为一种类型进行区分,根据position、及group和child的数量可以计算出折叠或者展开之后的位置。 (2)抽象出getGroupCount、getGroupItem、onCreateGroupViewHolder、onBindGroupViewHolder (3)抽象出onCreateChildViewHolder、onBindChildViewHolder (4)抽象出BaseGroupBean,包含getChildCount、getChildAt、isExpandable方法 (5)在onCreateViewHolder中根据type进行创建不同的布局 ,并进行封装

代码语言:javascript
复制
switch (viewType & TYPE_MASK) {
            case TYPE_EMPTY:
                return mEmptyViewProducer.onCreateViewHolder(parent);
            case TYPE_HEADER:
                return mHeaderViewProducer.onCreateViewHolder(parent);
            case TYPE_FOOTER:
                return mFooterViewProducer.onCreateViewHolder(parent);
            case TYPE_LOAD_MORE:
                return mLoadMoreViewProducer.onCreateViewHolder(parent);
            case TYPE_CHILD:
                return onCreateChildViewHolder(parent, viewType ^ TYPE_CHILD);
            case TYPE_GROUP:
                return onCreateGroupViewHolder(parent, viewType ^ TYPE_GROUP);
            default:
                throw new IllegalStateException(
                        String.format(Locale.getDefault(), "Illegal view type : viewType[%d]", viewType));

        }

(6)在getItemCount中将几个类型的布局数量算进去 (7)在onBindViewHolder中进行实际数据绑定的封装。

代码语言:javascript
复制
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
        switch (holder.getItemViewType() & TYPE_MASK) {
            case TYPE_EMPTY:
                mEmptyViewProducer.onBindViewHolder(holder);
                break;
            case TYPE_HEADER:
                mHeaderViewProducer.onBindViewHolder(holder);
                break;
            case TYPE_FOOTER:
                mFooterViewProducer.onBindViewHolder(holder);
                break;
            case TYPE_LOAD_MORE:
                mLoadMoreViewProducer.onBindViewHolder(holder);
                if (mOnLoadMoreListener != null) {
                    mOnLoadMoreListener.onLoadMoreRequested();
                }
                break;
            case TYPE_CHILD:
                final int[] childCoord = translateToDoubleIndex(position);
                GroupBean groupBean = getGroupItem(childCoord[0]);
                bindChildViewHolder((ChildViewHolder) holder, groupBean, groupBean.getChildAt(childCoord[1]), payloads);
                break;
            case TYPE_GROUP:
                bindGroupViewHolder((GroupViewHolder) holder, getGroupItem(translateToDoubleIndex(position)[0]), payloads);
                break;
            default:
                throw new IllegalStateException(
                        String.format(Locale.getDefault(), "Illegal view type : position [%d] ,itemViewType[%d]", position, holder.getItemViewType()));
        }
    }

3. 持续迭代

  • 多种类型适配
  • 支持grid
  • 支持stickyHead

4. 效果图

效果图

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 用法
    • (1)基本可展开的group写法
      • (2)支持Header、Footer写法
        • (3)支持EmptyView写法
          • (4)支持LoadMore写法
            • (5)点击的监听
            • 2. 基本原理
            • 3. 持续迭代
            • 4. 效果图
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档