Android自定义任意层级树形控件
简介:
开发项目时,偶尔会遇到诸如展示公司员工结构,商品分类显示,文件管理…的问题。大家自然会想到ExpandableListView。但,问题是其目前基本只支持两级且数据集的组织较复杂。接下来,我给大家介绍一种自定义任意层级树形控件的方法。
效果展示图:
连真机演示
基本原理:
ListView’s item + paddingLeft(level) + expand + include
将数据库中的数据 Bean 转化wei树形结构里的 Node
通过 反射+注解 实现通用的获取任意Bean中的数据
主要代码逻辑:
将用户的数据转化为树的节点
设置节点间的关系(父子,兄弟)
对节点进行排序(形成树形结构)
过滤出需要在界面显示的数据
书写代码:
1)创建节点类Node
1_1)新建包bean——>FileBean.java(保存数据库实体属性)
代码如下:
package com.qiyu.treeview.bean;
/**
* Created by qiyu on 2016/4/29.
*/
public class FileBean {
private int id;//主键
private int PId;//父节点Id
private String label;//描述信息
private String desc;//其他描述信息
//....
public FileBean() {
}
public FileBean(int id, int PId, String label) {
this.id = id;
this.PId = PId;
this.label = label;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPId() {
return PId;
}
public void setPId(int PId) {
this.PId = PId;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
1_2)新建包utils—>Node.java(设置节点信息)
代码如下:
package com.qiyu.treeview.utils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by qiyu on 2016/4/29.
*/
public class Node {
private int id;//节点Id
private int PId = 0;//根节点PId为0,表示目前没有子节点
private String name;//节点描述信息
private int level;//节点层次
private boolean isExpand = false;//节点是否展开
private int icon;//节点图标
private Node parent;//父节点
private List<Node> children = new ArrayList<>();//子节点
public Node() {
}
public Node(int id, int PId, String name) {
this.id = id;
this.PId = PId;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPId() {
return PId;
}
public void setPId(int PId) {
this.PId = PId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setLevel(int level) {
this.level = level;
}
public boolean isExpand() {
return isExpand;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public List<Node> getChildren() {
return children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
//是否为根节点
public boolean isRoot() {
return parent == null;
}
//是否为叶子节点
public boolean isLeaf() {
return children.size() == 0;
}
//当前父节点的收缩状态
public boolean isParentExpand() {
if (parent == null) {
return false;
}
return parent.isExpand();
}
//设置节点收缩状态,如果父节点收缩,所有子节点也收缩
public void setExpand(boolean expand) {
isExpand = expand;
if (!isExpand) {
for (Node node : children) {
node.setExpand(false);
}
}
}
//获取节点层级
public int getLevel() {
return parent == null ? 0 : parent.getLevel() + 1;
}
}
2)将用户数据转化为Node节点
2_1)utils—>TreeHelper.java(辅助类:将Bean转化为Node)
代码如下(代码未完结):
package com.qiyu.treeview.utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Created by qiyu on 2016/4/29.
*/
//辅助类:将Bean转化为Node
public class TreeHelper {
public static <T> List<Node> convertData2Nodes(List<T> datas) throws IllegalAccessException {
List<Node> nodes = new ArrayList<>();
Node node = null;
/*循环遍历用户Bean数据,将其依次加入Node中:
* 通过T—>找到相应的class—>对应的属性field—>加入node
* */
for (T t : datas) {
int id = -1;
int pid = -1;
String label = null;
node = new Node();
Class clazz = t.getClass();
Field[] fields = clazz.getFields();
for (Field field : fields) {
//1,命名规范。PS:id统一为nodeId....不灵活,用户体验不好
//2,注解+反射。注解:定位,给id加一个标志;反射:通过注解取值
}
//遍历完属性,将id,pid,label添加到node中
node = new Node(id, pid, label);
nodes.add(node);
}
return nodes;
}
}
2_2)utils—>annotation—>TreeNodeId.java(为FileBean里的id添加注解)
代码如下:
package com.qiyu.treeview.utils.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by qiyu on 2016/5/3.
*/
//注解的声明