利用listView打造层级列表菜单

 git

这是一个层级列表的源码,可以无限打造层级深度

1.Node类 

package com.example.utils;

import java.util.ArrayList;
import java.util.List;

public class Node {
    private int id;
    private int pid= 0;             //根节点

    private String name;
    private int level;              //树木的层级

    private boolean isExpand = false;       //是否展开
    private int icon;                       //图标

    private Node parent;
    private List<Node> children = new ArrayList<Node>();

    public Node(int id, int pid, String name) {
        this.id = id;
        this.pid = pid;
        this.name = name;
    }

    public Node() {
    }

    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 int getLevel() {
        return parent == null ? 0 : parent.getLevel() + 1;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public boolean isExpand() {
        return isExpand;
    }

    public void setExpand(boolean expand) {
        isExpand = expand;
        if (!isExpand){
            for (Node node : children){
                node.setExpand(false);
            }
        }
    }

    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 isParentExpand(){
        if (parent ==null){
            return false;
        }else {
            return parent.isExpand();
        }
    }

    //判断是否是叶节点
    public boolean isLeaf(){
        return children.size() == 0;
    }


}

2.TreeHelper类 

package com.example.utils;

import com.example.annotation.TreeNodeId;
import com.example.annotation.TreeNodeLabel;
import com.example.annotation.TreeNodepId;
import com.example.threedemo.R;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class ThreeHelper {

    //将用户数据转化为树形数据
    public static <T>List<Node> conver2Datas2Nodes(List<T> datas) throws IllegalAccessException {

        List<Node> nodes = new ArrayList<>();
        Node node = null;
        for (T t : datas){
            int id= -1;
            int pid = -1;
            String lable = null;
            node = new Node();
            Class clazz = t.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields){
                if (field.getAnnotation(TreeNodeId.class) != null){
                    field.setAccessible(true);
                    id = field.getInt(t);
                }
                if (field.getAnnotation(TreeNodepId.class) != null){
                    field.setAccessible(true);
                    pid = field.getInt(t);
                }
                if (field.getAnnotation(TreeNodeLabel.class) != null){
                    field.setAccessible(true);
                    lable = (String) field.get(t);
                }
            }
            node = new Node(id,pid,lable);
            nodes.add(node);
        }
        //设置node间的节点关系
        for (int i = 0;i <nodes.size(); i ++){
            Node n = nodes.get(i);
            for (int j = i+1;j < nodes.size();j++){
                Node m = nodes.get(j);
                if (m.getPid() == n.getId()){
                    n.getChildren().add(m);
                    m.setParent(n);
                }else if (m.getId() == n.getPid()){
                    m.getChildren().add(n);
                    n.setParent(m);
                }
            }
        }

        for(Node n: nodes){
            setNodeIcon(n);
        }
        return nodes;
    }

    public static <T> List<Node> getSortedNodes(List<T> datas,int defaultExpandLexel) throws IllegalAccessException {
        List<Node> result = new ArrayList<>();
        List<Node> nodes = conver2Datas2Nodes(datas);
        //获取根节点
        List<Node> rootNodes = getRootNodes(nodes);
        for (Node node: rootNodes){
            addNode(result,node,defaultExpandLexel,1);
        }

        return result;
    }
    //过滤出可见的节点
    public static List<Node> filterVisbileNodes(List<Node> nodes){
        List<Node> reuslt = new ArrayList<>();
        for (Node node : nodes){
            if (node.isRoot() || node.isParentExpand()) {
                setNodeIcon(node);
                reuslt.add(node);
            }
        }
        return reuslt;
    }

    //把一个节点的所有孩子节点放入rusult
    private static void addNode(List<Node> result, Node node, int defaultExpandLexel, int currentLevel) {
        result.add(node);
        if (defaultExpandLexel >= currentLevel){
            node.setExpand(true);
        }
        if (node.isLeaf()){
            return;
        }else {
            for (int i = 0;i < node.getChildren().size();i ++){
                addNode(result,node.getChildren().get(i),defaultExpandLexel,currentLevel + 1);
            }
        }

    }

    //从所有节点中获取根节点
    private static List<Node> getRootNodes(List<Node> nodes) {
        List<Node> root = new ArrayList<>();
        for (Node node : nodes){
            if (node.isRoot()){
                root.add(node);
            }
        }
        return root;
    }

    //为Node设置图标
    private static void setNodeIcon(Node n) {
        if (n.getChildren().size() > 0&& n.isExpand()){
            n.setIcon(R.drawable.down);
        }else if (n.getChildren().size() > 0&& !n.isExpand()){
            n.setIcon(R.drawable.right);
        }else {
            n.setIcon(-1);
        }
    }
}

 3.SimpleTreeListViewAdapter类

package com.example.utils.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.example.threedemo.R;
import com.example.utils.Node;
import com.example.utils.ThreeHelper;

import java.util.List;

public class SimpleTreeListViewAdapter<T> extends TreeListViewAdapter<T> {
    public SimpleTreeListViewAdapter(ListView tree, Context context,
                                     List<T> dates, int defaultExpandLevel) throws IllegalAccessException {

        super(tree, context, dates, defaultExpandLevel);

    }


    @Override
    public View getConvertView(Node node, int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null){
            convertView = inflater.inflate(R.layout.list_item,parent,false);
            holder = new ViewHolder();
            holder.mIcon = (ImageView) convertView.findViewById(R.id.item_icon55);
            holder.mText = (TextView) convertView.findViewById(R.id.item_text55);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (node.getIcon() == -1){
            holder.mIcon.setVisibility(View.INVISIBLE);
        }else {
            holder.mIcon.setVisibility(View.VISIBLE);
            holder.mIcon.setImageResource(node.getIcon());
        }

        holder.mText.setText(node.getName());
        return convertView;
    }

    public void addExtraNode(int position, String toString) {
        Node node = mVisbleNodes.get(position);
        int index = mAllNodes.indexOf(node);
        //存储
        Node exNode = new Node(-1,node.getId(),toString);
        exNode.setParent(node);
        node.getChildren().add(exNode);
        mAllNodes.add(index+1,exNode);

        mVisbleNodes = ThreeHelper.filterVisbileNodes(mAllNodes);
        notifyDataSetChanged();
    }

    private class ViewHolder{
        ImageView mIcon;
        TextView mText;
    }
}

4.TreeListViewAdapter类 

package com.example.utils.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;

import com.example.utils.Node;
import com.example.utils.ThreeHelper;

import java.util.List;

public abstract class TreeListViewAdapter<T> extends BaseAdapter {

    protected Context mContext;
    protected List<Node> mAllNodes;
    protected List<Node> mVisbleNodes;
    protected LayoutInflater inflater;
    protected ListView mTree;

    public interface OnTreeNodeOnClickListener{
        void onClck(Node node,int position);
    }
    private OnTreeNodeOnClickListener mLisitener;

    public void setOnTreeNodeLisitener(OnTreeNodeOnClickListener mLisitener) {
        this.mLisitener = mLisitener;
    }

    public TreeListViewAdapter(ListView tree, Context context, List<T> dates, int defaultExpandLevel) throws IllegalAccessException {
        mContext = context;
        inflater = LayoutInflater.from(context);
        mAllNodes = ThreeHelper.getSortedNodes(dates,defaultExpandLevel);
        mVisbleNodes = ThreeHelper.filterVisbileNodes(mAllNodes);

        mTree = tree;
        mTree.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                expandOrCollapse(position);
                if (mLisitener != null){
                    mLisitener.onClck(mVisbleNodes.get(position),position);
                }
            }

        });

    }
    //点击收缩或展开
    private void expandOrCollapse(int position) {
        Node n = mVisbleNodes.get(position);
        if (n != null){
            if (n.isLeaf()){
                return;
            }
            n.setExpand(!n.isExpand());
            mVisbleNodes = ThreeHelper.filterVisbileNodes(mAllNodes);
            notifyDataSetChanged();

        }
    }
    @Override
    public int getCount() {
        return mVisbleNodes.size();
    }

    @Override
    public Object getItem(int i) {
        return mVisbleNodes.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Node node = mVisbleNodes.get(position);
        convertView = getConvertView(node,position,convertView,parent);
        //设置内边距
        convertView.setPadding(node.getLevel() * 30,3,3,3);

        return convertView;
    }
    public abstract View getConvertView(Node node,int position,View convertView,ViewGroup parent);
}








package com.example.bean;

import com.example.annotation.TreeNodeId;
import com.example.annotation.TreeNodeLabel;
import com.example.annotation.TreeNodepId;

public class FileBean {
    @TreeNodeId
    private int id;
    @TreeNodepId
    private int pid;
    @TreeNodeLabel
    private String lable;

    public FileBean(int id, int pid, String lable) {
        this.id = id;
        this.pid = pid;
        this.lable = lable;
    }

    private String desc;

    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 getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
package com.example.threedemo;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.example.bean.FileBean;
import com.example.bean.OrgBean;
import com.example.utils.Node;
import com.example.utils.adapter.SimpleTreeListViewAdapter;
import com.example.utils.adapter.TreeListViewAdapter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private SimpleTreeListViewAdapter<OrgBean> adapter;
    private List<FileBean> mDatas;
    //private List<OrgBean> mDatas2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.listView);
        initDate();
        
        try {
            adapter = new SimpleTreeListViewAdapter<OrgBean>(listView,this,mDatas2,0);
            listView.setAdapter(adapter);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        initEvent();
    }

    



    private void initEvent(){
        adapter.setOnTreeNodeLisitener(new TreeListViewAdapter.OnTreeNodeOnClickListener() {
            @Override
            public void onClck(Node node, int position) {
                if (node.isLeaf()){
                    Toast.makeText(MainActivity.this,node.getName(),Toast.LENGTH_SHORT).show();
                }
            }
        });
        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(final AdapterView<?> adapterView, View view, final int position, long l) {
                final EditText editText = new EditText(MainActivity.this);
                new AlertDialog.Builder(MainActivity.this).setTitle("标题").setView(editText)
                        .setPositiveButton("是", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        adapter.addExtraNode(position,editText.getText().toString());
                    }
                }).setNegativeButton("取消",null).show();
                return true;
            }
        });
    }
    private void initDate() {
        mDatas = new ArrayList<>();
        FileBean fileBean = new FileBean(1,0,"根目录1");
        mDatas.add(fileBean);
        fileBean = new FileBean(2,0,"根目录2");
        mDatas.add(fileBean);
        fileBean = new FileBean(3,0,"根目录3");
        mDatas.add(fileBean);
        fileBean = new FileBean(4,1,"根目录1-1");
        mDatas.add(fileBean);
        fileBean = new FileBean(5,1,"根目录1-1");
        mDatas.add(fileBean);
        fileBean = new FileBean(6,5,"根目录1-2-1");
        mDatas.add(fileBean);

        fileBean = new FileBean(7,3,"根目录3-1");
        mDatas.add(fileBean);
        fileBean = new FileBean(8,3,"根目录3-2");
        mDatas.add(fileBean);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值