美文网首页Android应用开发那些事
可展开Recyclerview适配器支持Header、Foote

可展开Recyclerview适配器支持Header、Foote

作者: jerryhigh | 来源:发表于2020-05-20 22:01 被阅读0次

    前言

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

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

    使用类:BaseExpandableRecyclerViewAdapter
    demo地址:

    1. 用法

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

    • a 新增 父SampleGroupBean和子SampleChildBean
    • b 定义对应的父ViewHolder和子ViewHolder
    • c 实现adapter中对应的onCreateGroupViewHolder和onCreateChildViewHolder、onBindGroupViewHolder和onBindChildViewHolder
    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写法

          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写法

          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写法

           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)点击的监听

                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进行创建不同的布局 ,并进行封装

    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中进行实际数据绑定的封装。

        @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. 效果图

    效果图

    相关文章

      网友评论

        本文标题:可展开Recyclerview适配器支持Header、Foote

        本文链接:https://www.haomeiwen.com/subject/qqroohtx.html