ExpandableRecyclerView
github:https://github.com/hgDendi/ExpandableRecyclerView
自定义支持二级菜单的RecyclerViewAdapter。
将展开闭合操作封装在了BaseExpandableRecyclerViewAdapter中,使整个使用方式充满弹性。
下方有具体使用方法,一般需要override 6个方法:
- getGroupCount
- getGroupItem
- onCreateGroupViewHolder
- onCreateChildViewHolder
- onBindGroupViewHolder
- onBindChildViewHolder
因为onCreateViewHolder和onBindViewHolder本来即是RecyclerViewAdapter需要强制Override的方法,这里按父子关系拆分成了两个方法。而getGroupCount和getGroupItem在大概率情况下都是基于List的简单一行代码即可实现,故而使用起来十分简便。
Gradle
1 | dependencies{ |
优点
- 使用便捷、简洁明了
- 最大程度保留RecyclerView的原生机制,滑动到具体条目才进行渲染,不会滑到另一个Group渲染另一个Group下所有子Item
- itemView的部分刷新,可以自定义展开、闭合时的刷新机制,避免GroupItem在展开闭合时刷新整个GroupItem(比如只是简单的箭头指向改变)
- 采用泛型,用户自定义传入参数,扩展性更高
使用方法
定义父子数据结构
其中GroupBean需要继承自BaseGroupBean并override三个方法。
- getChildCount
- 获取子节点个数
- isExpandable
- 是否为可展开的节点
- 默认实现可以是判断子节点是否为0,但是也可以做其他处理
- getChildAt
- 根据index获取对应的子节点数据结构
1 | class SampleGroupBean implements BaseExpandableRecyclerViewAdapter.BaseGroupBean<SampleChildBean> { |
定义对应的ViewHolder
其中Group对应的ViewHolder要继承BaseGroupViewHolder并改写onExpandStatusChanged.
该方法是实现item局部刷新的方法,在展开、闭合时会回调,比如对于大多数情况,开关闭合状态只需要修改左边箭头指向,就无需刷新itemView的其他部分。
实现原理是使用RecyclerView的payload机制实现局部监听刷新。
1 | static class GroupVH extends BaseExpandableRecyclerViewAdapter.BaseGroupViewHolder { |
使用自定义Adapter继承基类
1 | // !!注意这里继承时候使用的泛型,分别为上面提到的Bean和ViewHolder |
其他用法
增加父子的种类
通过改写getChildType和getGroupType方法进行控制type,该type会在onCreateGroupViewHolder和onCreateChildViewHolder时回传。
1 | protected int getGroupType(GroupBean groupBean) { |
增加列表为空时候的EmptyView
1 | adapter.setEmptyViewProducer(new ViewProducer() { |
增加HeaderView
1 | adapter.setEmptyViewProducer(new ViewProducer() { |
监听事件
可以通过setListener的方式设置监听事件。
1 | public interface ExpandableRecyclerViewOnClickListener<GroupBean extends BaseGroupBean, ChildBean> { |
实现原理
父子结构划分
- 通过getItemType判断所处类型,在基类中就先划分为四种类型的View。
1 | private static final int TYPE_EMPTY = ViewProducer.VIEW_TYPE_EMPTY; |
- 在onCreateViewHolder和onBindViewHolder中进行类型判断,调用不同的方法,这些方法在子类中进行重载。注意这里将这三个方法都置为final,防止子类重载,子类只能重载对应不同type的具体方法。
1 |
|
展开闭合操作
操作
当groupBean的isExpandable返回true的时候,为itemView设置点击事件,进行展开闭合。
展开闭合的具体原理是在Set中记录展开闭合情况,当发生展开、闭合操作的时候进行更新,并使用notifyItemChange接口进行列表的局部刷新。
1 | private Set<GroupBean> mExpandGroupSet; |
局部刷新原理
定义了Payload,采用Payload机制进行局部刷新。
在notifyItemChange时传入payload,在onBindViewHolder操作中判断是否带有payload,若带有payload,则执行部分刷新的操作。
1 | private static final Object EXPAND_PAYLOAD = new Object(); |