Android简单树状实现
使用ListView+BaseAdapter+自定义数据结构完美实现,不需要第三方库。简单,方便,快捷……
节点类Node
public class Node<T> {
private int _id; //节点id
private Node _parent; //父节点
private List<Node> _children = new ArrayList<>(); //所有的儿子节点
private T obj; //依附这个节点的用户对象
private int _size_all; //本节点对应的树的大小(计算其下所有的节点,无论展开状态是啥)
private int _size_expand; //本节点对应的树展开状态大小
private boolean isExpand = true; //本节点的展开状态
public Node(int id, T obj) {
this._id = id;
this.obj = obj;
_size_expand = 1;
_size_all = 1;
}
Node get_parent() {
return _parent;
}
void set_parent(Node node) {
this._parent = node;
}
List<Node> get_children() {
return _children;
}
int get_size(boolean isExpand) {
return isExpand ? _size_expand : _size_all;
}
void set_size(int size, boolean isExpand) {
if (isExpand)
_size_expand = size;
else
_size_all = size;
}
//在当前这个node为根的树上寻找等于id的node,如果找不到,返回null
//isExpand:
//true:表示在expand树上查找
// false: 表示不考虑expand属性,在整颗树上找
Node find_Node_By_Id(int id, boolean isExpand) {
if (this.get_id() == id)
return this;
List<Node> list = this.get_children();
if (list.size() == 0) {
return null;
} else {
if ((isExpand && this.getExpand()) || !isExpand) {
for (Node node : this.get_children()) {
Node result = node.find_Node_By_Id(id, isExpand);
if (result != null)
return result;
}
}
}
return null;
}
//按照深度优先,遍历以本节点为根的整个树,返回第position个元素的node
//position从0开始
//isExpand:
//true:表示在expand树上查找
// false: 表示不考虑expand属性,在整颗树上找
Node get(int position, boolean isExpand) {
if (position == 0)
return this;
position--;
List<Node> list = this.get_children();
if (list.size() == 0) {
return null;
} else {
if (!isExpand || (isExpand && this.getExpand())) {
for (Node node : this.get_children()) {
int size = position - node.get_size(isExpand);
if (size < 0) {
return node.get(position, isExpand);
} else {
position = size;
}
}//for
}//if
}//if
return null;
}
void setExpand(boolean expand) {
isExpand = expand;
}
boolean getExpand() {
return isExpand;
}
public boolean isLeaf() {
return this.get_children().size() == 0;
}
public boolean isExpand() {
return isExpand;
}
public int get_id() {
return _id;
}
public int get_level() {
if (_parent != null)
return _parent.get_level() + 1;
else
return 0;
}
public T getObject() {
return obj;
}
}
树节点(根节点)Tree
public class Tree<T> {
private final String TAG = "Tree";
private Node root;
public Tree() {
root = new Node(-1, null);
}
public boolean addRoot(int id, T t) {
if (id < 0) {
Log.w(TAG, "addRoot: node.id cannot be less than 0");
return false;
}
//必须在所有的节点中查找
if (findNode(id) == null) {
addNodeToParent(new Node(id, t), root);
} else {
Log.w(TAG, String.format("addRoot: node.id=%d exists!", id));
return false;
}
return true;
}
public boolean addLeaf(int id, int pid, Object object) {
if (id < 0 || pid < 0) {
Log.w(TAG, "addNode: id or pid should not be less than 0");
return false;
}
Node node = findNode(id);
if (node != null) {
Log.w(TAG, String.format("addNode: node.id=%d exists", id));
return false;
}
Node parent = findNode(pid);
if (parent == null) {
Log.w(TAG, String.format("addNode: cannot find parent with id=", pid));
return false;
}
node = new Node(id, object);
addNodeToParent(node, parent);
return true;
}
//将一个节点挂在父节点下面
private void addNodeToParent(Node node, Node parent) {
node.set_parent(parent);
parent.get_children().add(node);
while (parent != null) {
parent.set_size(parent.get_size(false) + node.get_size(false), false);
parent.set_size(parent.get_size(true) + node.get_size(true), true);
parent = parent.get_parent();
}
}
//删除一个节点
public void deleteNode(int id) {
if (id < 0) {
Log.w(TAG, "deleteNode: id should not be less than 0");
return;
}
Node node = findNode(id);
if (node == null) {
Log.w(TAG, "deleteNode: cannot find the node.id=" + id);
return;
}
Node parent = node.get_parent();
parent.get_children().remove(node);
while (parent != null) {
parent.set_size(parent.get_size(false) - node.get_size(false), false);
parent.set_size(parent.get_size(true) - node.get_size(true), true);
parent = parent.get_parent();
}
}
public Node findNode(int id) {
return root.find_Node_By_Id(id, false);
}
//按照深度优先,遍历整个树,返回第position个元素的node
//position从0开始
public Node getInAll(int position) {
return get(position, false);
}
//仅遍历可见部分
public Node getInCollapse(int position) {
return get(position, true);
}
private Node get(int position, boolean isExpand) {
return root.get(position + 1, isExpand);
}
public int sizeOfAll() {
return size(false);
}
public int sizeOfCollapse() {
return size(true);
}
//获取树的大小
//isExpand:
// true 表示展开可见的大小
// false 表示整棵树的大小
private int size(boolean isExpand) {
return root.get_size(isExpand) - 1;
}
//点击位置position,折叠或者展开节点
//return
// false: 表示没有做任何事情
public boolean expandOrCollapse(int position) {
Node node = getInCollapse(position);
if (node == null) {
Log.w(TAG, "expandOrCollapse: cannot find node at position=" + position);
return false;
}
if (node.isLeaf())
return false;
if (node.getExpand()) {
//折叠本节点
int sizedelta = node.get_size(true) - 1;
node.set_size(1, true);
Node parent = node.get_parent();
while (parent != null) {
if (parent.getExpand() == false) {
Log.e(TAG, String.format("expandOrCollapse: node.id should be collapsed!", parent.get_id()));
return false;
}
parent.set_size(parent.get_size(true) - sizedelta, true);
parent = parent.get_parent();
}
} else {
//展开本节点
int sizedelta = 0;
List<Node> children = node.get_children();
for (Node son : children) {
sizedelta += son.get_size(true);
}
node.set_size(1 + sizedelta, true);
Node parent = node.get_parent();
while (parent != null) {
if (parent.getExpand() == false) {
Log.e(TAG, String.format("expandOrCollapse: node.id should be collapsed!", parent.get_id()));
return false;
}
parent.set_size(parent.get_size(true) + sizedelta, true);
parent = parent.get_parent();
}
}
node.setExpand(!node.getExpand());
return true;
}
}
TreeListViewAdapter只需要重写getCount,getItem,getView即可
@Override
public int getCount() {
return mTree == null ? 0 : mTree.sizeOfCollapse();
}
@Override
public Node getItem(int position) {
return mTree == null ? null : mTree.getInCollapse(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
Node node = mTree.getInCollapse(position);
view.setPadding(node.get_level() * 30, 3, 3, 3);
return view;
}
使用代码片段
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tree);
mTree.addRoot(0, "");
mTree.addLeaf(1, 0, "a");
mTree.addLeaf(2, 0, "b");
mTree.addLeaf(3, 0, "c");
mTree.addLeaf(5, 0, "d");
mTree.addLeaf(4, 2, "e");
mTree.addLeaf(7, 4, "f");
mTree.addLeaf(8, 7, "g");
mTree.addLeaf(9, 8, "h");
mTree.addLeaf(6, 5, "i");
ListView listView = findViewById(R.id.listViewTree);
myAdapter = new TreeListViewAdapter(this, R.layout.tree_item_layout, mTree);
listView.setAdapter(myAdapter);
listView.setOnItemClickListener((parent, view, position, id) -> {
if (mTree == null) return;
mTree.expandOrCollapse(position);
myAdapter.notifyDataSetChanged();
onClick(mTree.getInCollapse(position), position);
});
}
效果图