Android简单树状实现

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);
        });
    }

效果图
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值