zoukankan      html  css  js  c++  java
  • Android 树形菜单

    首先来一张萌萌哒的效果图(比较懒 - -)

    然后是代码:

    //  Node
    package com.example.treeview.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Node {
    
        public Node() {
            super();
        }
    
        public Node(int id, int pId, String name) {
            super();
            this.id = id;
            this.pId = pId;
            this.name = name;
        }
    
        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>();
    
        /**
         * 判断是否为根节点
         * 
         * @return
         */
        public boolean isRoot() {
            return parent == null;
        }
    
        public int getId() {
            return id;
        }
    
        /**
         * 判断当前父节点是否展开
         * 
         * @return
         */
        public boolean isparentExpand() {
            if (parent == null) {
                return false;
            } else {
                return parent.isExpand;
            }
        }
    
        /**
         * 判断是否为叶节点
         * 
         * @return
         */
        public boolean isLeaf() {
            return children.size() == 0;
        }
    
        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;
        }
    
        /**
         * 得到当前节点的层级
         * 
         * @return
         */
        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 isExpand) {
            this.isExpand = isExpand;
            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;
        }
    
    }
    //FileBean
    package com.example.treeview.bean;
    
    import com.example.treeview.utils.annotation.TreeNodeId;
    import com.example.treeview.utils.annotation.TreeNodeLable;
    import com.example.treeview.utils.annotation.TreeNodePid;
    
    public class FileBean {
    
        @TreeNodeId
        private int id;
        @TreeNodePid
        private int pId;
        @TreeNodeLable
        private String label;
    
        public FileBean(int id, int pId, String label) {
            super();
            this.id = id;
            this.pId = pId;
            this.label = label;
        }
    
        private String desc;
    }
    // 注解
    package com.example.treeview.utils.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME.RUNTIME)
    public @interface TreeNodeId {
    
    }
    
    package com.example.treeview.utils.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME.RUNTIME)
    public @interface TreeNodeLable {
    
    }
    
    
    
    package com.example.treeview.utils.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME.RUNTIME)
    public @interface TreeNodePid {
    
    }
    //TreeHelper
    package com.example.treeview.utils;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.example.treeview.utils.annotation.TreeNodeId;
    import com.example.treeview.utils.annotation.TreeNodeLable;
    import com.example.treeview.utils.annotation.TreeNodePid;
    
    public class TreeHelper {
    
        /**
         * 将用户的数据转化为树形数据
         * 
         * @param datas
         * @return
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static <T> List<Node> convertDatasNodes(List<T> datas)
                throws IllegalAccessException, IllegalArgumentException {
            List<Node> nodes = new ArrayList<Node>();
            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(TreeNodeLable.class) != null) {
                        field.setAccessible(true);
                        lable = (String) field.get(t);
                    }
                }
                node = new Node(id, pId, lable);
                nodes.add(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;
        }
    
        
        /**
         * 设置过滤出可见的节点
         * @param nodes
         * @return
         */
        public static List<Node> filterVisibleNodeS(List<Node> nodes){
            List<Node> reuslt=new ArrayList<Node>();
            for (Node node : nodes) {
                if (node.isRoot()||node.isparentExpand()) {
                    setNodeIcon(node);
                    reuslt.add(node);
                }
            }
            return reuslt;
        }
        
        /**
         * 
         * @param datas
         * @return
         * @throws IllegalArgumentException 
         * @throws IllegalAccessException 
         */
        public static <T> List<Node> getSortedNodes(List<T> datas,int defaultExpandLevel) throws IllegalAccessException, IllegalArgumentException{
            List<Node> result=new ArrayList<Node>();
            List<Node> nodes=convertDatasNodes(datas);
            List<Node> rootNodes=getRootNodes(nodes);
            for (Node node : rootNodes) {
                AddNode(result,node,defaultExpandLevel,1);
            }
            return result;
        }
        
        /**
         * 把一个节点的所有孩子节点都放入result
         * @param result
         * @param node
         * @param defaultExpandLevel
         * @param currentLevel
         */
        private static void AddNode(List<Node> result, Node node,
                int defaultExpandLevel, int currentLevel) {
            result.add(node);
            if (defaultExpandLevel>=currentLevel) {
                node.setExpand(true);
            }
            if (node.isLeaf()) {
                return;
            }
            for (int i = 0; i < node.getChildren().size(); i++) {
                AddNode(result, node.getChildren().get(i), defaultExpandLevel, currentLevel+1);
            }
        }
    
    
        /**
         * 从所有节点中过滤出根节点
         * @param nodes
         * @return
         */
        private static List<Node> getRootNodes(List<Node> nodes) {
            List<Node> root=new ArrayList<Node>();
            for (Node node : nodes) {
                if (node.isRoot()) {
                    root.add(node);
                }
            }
            return root;
        }
    
    
        /**
         * 为Node设置图标
         * @param n
         */
        private static void setNodeIcon(Node n) {
            if (n.getChildren().size()>0&&n.isExpand()) {
                n.setIcon(0);
            }else if(n.getChildren().size()>0&&!n.isExpand()){
                n.setIcon(1);
            }else {
                n.setIcon(-1);
            }
        }
    }
    //TreeListViewAdapter
    package com.example.treeview.adapter;
    
    import java.util.List;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.BaseAdapter;
    import android.widget.ListView;
    
    import com.example.treeview.utils.Node;
    import com.example.treeview.utils.TreeHelper;
    
    public abstract class TreeListViewAdapter<T> extends BaseAdapter {
    
        protected Context mContext;
        protected List<Node> mAllNodes;
        protected List<Node> mVisibleNodes;
        protected LayoutInflater mInflater;
        protected ListView mTree;
    
        /**
         * 设置Node的点击回调
         * 
         * @author az
         * 
         */
        private interface OnTreeNodeClickListener {
            void onClick(Node node, int position);
        }
    
        private OnTreeNodeClickListener mListener;
    
        public void setOnTreeNodeClickListener(OnTreeNodeClickListener mListener) {
            this.mListener = mListener;
        }
    
        public OnTreeNodeClickListener getmListener() {
            return mListener;
        }
    
        public void setmListener(OnTreeNodeClickListener mListener) {
            this.mListener = mListener;
        }
    
        public TreeListViewAdapter(ListView mTree, Context context, List<T> datas,
                int defaultExpandLevel) throws IllegalAccessException,
                IllegalArgumentException {
            this.mContext = context;
            this.mInflater = LayoutInflater.from(context);
            this.mAllNodes = TreeHelper.getSortedNodes(datas, defaultExpandLevel);
            this.mVisibleNodes = TreeHelper.filterVisibleNodeS(mAllNodes);
            this.mTree = mTree;
            this.mTree.setOnItemClickListener(new OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {
                    expandOrCollapse(position);
                    if (mListener != null) {
                        mListener.onClick(mVisibleNodes.get(position), position);
                    }
                }
            });
        }
    
        /**
         * 点击收缩或者展开
         * 
         * @param position
         */
        private void expandOrCollapse(int position) {
            Node n = mVisibleNodes.get(position);
            if (n != null) {
                if (n.isLeaf())
                    return;
                n.setExpand(!n.isExpand());
                mVisibleNodes = TreeHelper.filterVisibleNodeS(mAllNodes);
                notifyDataSetChanged();
            }
        }
    
        @Override
        public int getCount() {
            return mVisibleNodes.size();
        }
    
        @Override
        public Object getItem(int position) {
            return mVisibleNodes.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Node node=mVisibleNodes.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);
    
    }
    //SimpleTreeListViewAdapter   继承TreeLivewAdapter方便使用
    package com.example.treeview.adapter;
    
    import java.util.List;
    
    import com.example.threeview.R;
    import com.example.treeview.utils.Node;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class SimpleTreeListViewAdapter<T> extends TreeListViewAdapter<T> {
    
        public SimpleTreeListViewAdapter(ListView mTree, Context context,
                List<T> datas, int defaultExpandLevel)
                throws IllegalAccessException, IllegalArgumentException {
            super(mTree, context, datas, defaultExpandLevel);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public View getConvertView(Node node, int position, View convertView,
                ViewGroup parent) {
            ViewHolder holder=null;
            if (convertView==null) {
                convertView=mInflater.inflate(R.layout.list_item, parent,false);
                holder=new ViewHolder();
                holder.mIcon=(ImageView) convertView.findViewById(R.id.iv_itemicon);
                holder.mText=(TextView) convertView.findViewById(R.id.tv_itemtext);
                convertView.setTag(holder);
            }else {
                holder=(ViewHolder) convertView.getTag();
            }
            holder.mText.setText(node.getName());
            return convertView;
        }
        
        private class ViewHolder{
            ImageView mIcon;
            TextView mText;
        }
    
    }
    //MainActivity
    
    package com.example.treeview;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.example.threeview.R;
    import com.example.treeview.adapter.SimpleTreeListViewAdapter;
    import com.example.treeview.bean.FileBean;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
        private ListView mTree;
        private SimpleTreeListViewAdapter<FileBean> mAdapter;
        private List<FileBean> mDatas;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mTree=(ListView) findViewById(R.id.lv);
            initDatas();
            try {
                mAdapter=new SimpleTreeListViewAdapter<>(mTree, this, mDatas, 0);
                mTree.setAdapter(mAdapter);
            } catch (IllegalAccessException | IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        private void initDatas() {
            mDatas=new ArrayList<FileBean>();
            FileBean bean=new FileBean(1, 0, "根1");
            mDatas.add(bean);
            bean=new FileBean(2, 0, "根2");
            mDatas.add(bean);
            bean=new FileBean(3, 1, "根1-1");
            mDatas.add(bean);
            bean=new FileBean(4, 2, "根2-1");
            mDatas.add(bean);
        }
    
        
    }

    在上面的adapter里面有自定义的一个,使用方法:

    mAdapter.setOnTreeNodeClickListener(new );

    提供了一个OnClick方法:

    onClick(Node node, int position)

    参考:http://www.imooc.com/learn/303

  • 相关阅读:
    680C. Bear and Prime 100 数学
    Codeforces 681C. Heap Operations 优先队列
    Codeforces C. NP-Hard Problem 搜索
    Codeforces 689C. Mike and Chocolate Thieves 二分
    Codeforces 689B. Mike and Shortcuts SPFA/搜索
    Codeforces Round #223 (Div. 2) E. Sereja and Brackets 线段树区间合并
    Educational Codeforces Round 1 E. Chocolate Bar dp
    Testing Round #12 A,B,C 讨论,贪心,树状数组优化dp
    Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map
    hdu 3706 Second My Problem First 单调队列
  • 原文地址:https://www.cnblogs.com/stareblankly/p/5009871.html
Copyright © 2011-2022 走看看