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 可以实现该抽象类。
字段方法解析:
- mExpandable 保存当前的状态值,默认为 false
- mSubItems 存储数据 bean 集合
里面还包装了一些常用的方法,这里就不一一解析了。
接下来我们以一个使用 demo 的实现来进行分析:
我们可以看群主 demo 中的 ExpandableUseActivity :
private ArrayList generateData() {
int lv0Count = 9;
int lv1Count = 3;
int personCount = 5;
String[] nameList = {"Bob", "Andy", "Lily", "Brown", "Bruce"};
Random random = new Random();
ArrayList res = new ArrayList<>();
for (int i = 0; i < lv0Count; i++) {
Level0Item lv0 = new Level0Item("This is " + i + "th item in Level 0", "subtitle of " + i);
for (int j = 0; j < lv1Count; j++) {
Level1Item lv1 = new Level1Item("Level 1 item: " + j, "(no animation)");
for (int k = 0; k < personCount; k++) {
lv1.addSubItem(new Person(nameList[k], random.nextInt(40)));
}
lv0.addSubItem(lv1);
}
res.add(lv0);
}
return res;
}
这段代码的作用是生成一个支持 Expandable and collapse 的数据集合,创建一个 0 级的 LevelOItem 然后将下一级的 Level1Item 添加到 Level0Item 中。
public class Level0Item extends AbstractExpandableItem implements MultiItemEntity {
public String title;
public String subTitle;
public Level0Item( String title, String subTitle) {
this.subTitle = subTitle;
this.title = title;
}
@Override
public int getItemType() {
return ExpandableItemAdapter.TYPE_LEVEL_0;
}
@Override
public int getLevel() {
return 0;
}
}
可以看到 Level0Item 继承了 AbstractExpandableItem 并实现 MultiItemEntity 接口。里面根据实际需求定义相应的字段即可。
Level1Item 与 Level0Item 一样,只是返回的 Level =1:
public class Level1Item extends AbstractExpandableItem implements MultiItemEntity{
public String title;
public String subTitle;
public Level1Item(String title, String subTitle) {
this.subTitle = subTitle;
this.title = title;
}
@Override
public int getItemType() {
return ExpandableItemAdapter.TYPE_LEVEL_1;
}
@Override
public int getLevel() {
return 1;
}
}
当如过某一级的 item 没有下一级的 list 时,就不需要在实现 AbstractExpandableItem 了
然后我们的切入点时 adapter,因为默认是折叠状态,当我们点击具备展开折叠能力的 item 时才会触发该功能,所以逻辑的控制是在 adapter 中的。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于