version:2.8.5
更多分享请看:http://cherylgood.cn
今天我们来学习BaseRecyclerViewAdapterHelper中有关实现可展开和折叠二级Item或多级Item的源码。在开始学习之前,我想先分析下实现的思路,这样对于进行源码的理解效果比较好。
实现伸展and折叠,很多控件都有,网上也有用linearlayout实现的功能很强大、很炫酷的开源项目,平时要实现一些伸缩性的自定义控件,我们也可以是用属性动画,或者动态控制控件的Layout属性等都可以实现。那么现在我们来想象一下,如果在recyclerview中实现该功能,相对来说能想到的比较合适的方式是什么呢?
其实我们可以很好的利用RecyclerView.Adapter给我们提供的如下一些通知数据源更新的方法来实现我们的动态伸展and折叠功能。当要伸展时,我们动态将下一级item的数据添加在与adapter绑定的数据集合中,然后通知layoutManger更新数据源。当要收缩时,同理,将下一级的item的数据源从与adapter绑定的数据集合中移除,然后通知更新。
* @see #notifyItemChanged(int)
* @see #notifyItemInserted(int)
* @see #notifyItemRemoved(int)
* @see #notifyItemRangeChanged(int, int)
* @see #notifyItemRangeInserted(int, int)
* @see #notifyItemRangeRemoved(int, int)
思路:
- 数据bean应该有存储自己数据的字段
- 数据bean应该有存储下一级item列表的集合类型的字段
- 数据bean应该有一个字段标识当前item的状态(伸展or收缩)
- 初始化adapter时只渲染顶级的item
- 点击item是检测该item是否支持伸缩
- 支持伸缩:当前状态展开->折叠(将次级list插入adapter绑定的data集合中,刷新数据);当前状态折叠->展开(将次级的list从与adapter绑定的data集合中移除,刷新数据)
- 插入或移除的位置根据点击的item确定,插入量与移除量根据下一级item数量确定
- 插入移除过程中可以使用动画效果
思路理清之后我们接下来开始学习源代码:
实现Expandable And collapse 效果我们仍然是使用BaseMultiItemQuickAdapter实现即可
然后我们需要先看两个相关的类:IExpandable接口;AbstractExpandableItem: 对数据bean的再次封装,某个bean如果有次级的list 可以实现该抽象类。
package com.chad.library.adapter.base.entity;
import java.util.List;
/**
* implement the interface if the item is expandable
* Created by luoxw on 2016/8/8.
*/
public interface IExpandable {
boolean isExpanded();
void setExpanded(boolean expanded);
List getSubItems();
/**
* Get the level of this item. The level start from 0.
* If you don't care about the level, just return a negative.
*/
int getLevel();
}
可以看到,IExpandable 里面定义了四个接口方法:
- isExpanded判断当前的bean是否已展开
- setExoanded更新bean的当前状态
- getSubItems返回下一级的数据集合
- getLevel 返回当前item属于第几个层级, 第一级from 0
package com.chad.library.adapter.base.entity;
import java.util.ArrayList;
import java.util.List;
/**
*
A helper to implement expandable item.
*
if you don't want to extent a class, you can also implement the interface IExpandable
* Created by luoxw on 2016/8/9.
*/
public abstract class AbstractExpandableItem implements IExpandable {
protected boolean mExpandable = false;
protected List mSubItems;
@Override
public boolean isExpanded() {
return mExpandable;
}
@Override
public void setExpanded(boolean expanded) {
mExpandable = expanded;
}
@Override
public List getSubItems() {
return mSubItems;
}
public boolean hasSubItem() {
return mSubItems != null && mSubItems.size() > 0;
}
public void setSubItems(List list) {
mSubItems = list;
}
public T getSubItem(int position) {
if (hasSubItem() && position < mSubItems.size()) {
return mSubItems.get(position);
} else {
return null;
}
}
public int getSubItemPosition(T subItem) {
return mSubItems != null ? mSubItems.indexOf(subItem) : -1;
}
public void addSubItem(T subItem) {
if (mSubItems == null) {
mSubItems = new ArrayList<>();
}
mSubItems.add(subItem);
}
public void addSubItem(int position, T subItem) {
if (mSubItems != null && position >= 0 && position < mSubItems.size()) {
mSubItems.add