二级listview我们可以使用expandablelistview,可以解决问题,但是要是多级的listview我们该怎么办。
网上有一个办法就是expandablelistview嵌套expandablelistview,我曾经以为这个可以解决问题,但是在实际应用中发现,子expandablelistview是不能张开的,整个视图的效果不是很好。
现在我来介绍一下我的方法。首先我们需要理解数据和视图是分开的,抛开两级、三级listview的束缚,界面是界面,数据是数据。我们只用最简单的listview,然后我们不改变数据源,那么我们改变的是什么了,通过索引寻找数据的方式。进一步说就是改变adapter中计算数据的数目方法和通过position找数据的方法。
这是一张树形数据结构的图,上面标注了每个索引。我们可以把它当作是完全展开,或者有些数据被隐藏了,我们不考虑隐藏的节点,它无关整个数据的多少和每个节点的索引。
下面是我的数据模型。
private Object obj;
public List<TreeNode> child;
public boolean isOpenChild;
obj代表自己的数据,child代表子类的数据,每个子类必须放在父类的child列表中去,isOpenChild是否开发子类,这个和adapter中数据的多少和寻找数据的方法有关。
下面是计算当前状态下有多少数据,listview中显示多少计算多少,会更具数据的isOpenChild计算。当前索引值的只计算子类和子类的子类的数据,不计算自身。
// 只计算子类和子类的直接子类、间接子类的数目
public int getChildSize() {
int size = 0;
// 判断子类集合对象是否为空
if (child == null) {
System.out.println("子类对象为空" + obj.toString());
return size;
}
// 子类集合大小为零 或者 不开放子类
if (child.size() == 0 || isOpenChild == false) {
System.out.println("子类对象数目为空" + obj.toString());
return size;
}
for (int i = 0; i < child.size(); i++) {
// 计算特定索引值的子类的所包含的大小
// 1 代表子类 child.get(i).getSize()是子类的所包含的数目
size += child.get(i).getChildSize() + 1;
}
return size;
}
下面是通过position寻找子类的方法。
节点被隐藏了,那么树形数据的数目变成了5,而有些结点的索引也发生了改变。
我们根据索引值i进行寻找数据,如果i==3:
节点不对,那进入第一个子树,i需要减少1。 i = 2
进入第2个节点, i = i - 1 =1;
进入第2个节点的第一个子节点, i = i - 1 =0;
第2个节点的第一个子节点
原则:1.判断i==0? 等于0说明找到了;
2.进入子树 i--;
3.进入兄弟减去子树的数目(包括子树和子树下面的所有节点);
/**
* 通过索引值寻找子类信息
*
* @param index
* @return
*/
public TreeNode findItemById(int index) {
int secondIndex = index;
int size = child.size();
TreeNode node = null;
for (int i = 0; i < size; i++) {
// 判断当前索引是否为0
if (secondIndex == 0) {
node = child.get(i);
break;
}
// 判断第二索引值和第i项item的子类数目
int reduce = secondIndex - child.get(i).getChildSize() - 1;
if (reduce >= 0) {
// 如果大于,继续寻找
secondIndex = reduce;
} else {
// 如果小于,寻找子类的子类
node = child.get(i).findItemById(secondIndex - 1);
break;
}
}
return node;
}
这两个方法已经介绍完毕,它们会被运用与adpater的getItem()和getCount()两个函数中去,listview的getview改怎么写怎么写,不用管多少级。当你点击的时候,改变当前item对应数据的isOpenChild的值,然后刷新一下列表。
欢迎大家多评论、多交流共同进步