Android提高十七篇之多级树形菜单的实现

本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!

       在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。本文程序运行效果图:

当用BaseExpandableListAdapter来实现二级树形菜单时,父项(getGroupView())和子项(getChildView())都是使用TextView。当要实现三级树形菜单时,子项(getChildView())就必须使用ExpandableList了.......另外还要定义结构体来方便调用三级树形的数据,二级树形菜单可以用如下:

三级树形菜单可以用如下,子项是二级树形菜单的结构体:

实现三级树形菜单有两点要注意的:

1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;

2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。

PS:本文在解决No.2关键点的时候,只能取得第三级选中的序号.....而第一,第二级依然无法获取其序号。

main.xml源码如下:

testExpandableList.java是主类,调用其他工具类,源码如下:

TreeViewAdapter.java是实现二级树形菜单的工具类,源码如下:

SuperTreeViewAdapter.java是实现三级树形菜单的工具类,会用到TreeViewAdapter.java,源码如下:

总结,使用ExpandableList实现三级树形菜单时有些bug不好解决,而且定义三维数组的时候也要倍加小心......所以尽量把数据化简来使用二级树形菜单。

  • 5
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 78
    评论
Android ListView 可以通过自定义适配器来实现多级树形列表。具体步骤如下: 1. 定义每个节点的数据模型,包括节点名称、节点ID、父节点ID等信息。 2. 自定义适配器,继承自 BaseAdapter,重写 getView() 方法,在该方法中根据节点的深度来确定每个节点的缩进距离,并根据节点状态显示不同的图标。 3. 在 Activity 的 onCreate() 方法中初始化树形数据,使用适配器将数据绑定到 ListView 上。 4. 在适配器中实现节点的展开和折叠功能,可以通过设置节点的可见性来实现。 5. 在 ListView 的 OnItemClickListener 中监听每个节点的点击事件,根据节点状态来判断是展开还是折叠。 示例代码如下: 1. 定义节点数据模型 ```java public class TreeNode { private int nodeId; private int parentId; private String nodeName; // 省略 getter 和 setter 方法 } ``` 2. 自定义适配器 ```java public class TreeAdapter extends BaseAdapter { private List<TreeNode> nodes; private LayoutInflater inflater; public TreeAdapter(Context context, List<TreeNode> nodes) { this.nodes = nodes; inflater = LayoutInflater.from(context); } @Override public int getCount() { return nodes.size(); } @Override public Object getItem(int position) { return nodes.get(position); } @Override public long getItemId(int position) { return nodes.get(position).getNodeId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.tree_item, null); holder = new ViewHolder(); holder.icon = convertView.findViewById(R.id.icon); holder.name = convertView.findViewById(R.id.name); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } TreeNode node = nodes.get(position); holder.name.setText(node.getNodeName()); int level = getLevel(node); holder.icon.setPadding(30 * (level + 1), holder.icon.getPaddingTop(), holder.icon.getPaddingRight(), holder.icon.getPaddingBottom()); if (hasChildren(node)) { holder.icon.setImageResource(node.isExpanded() ? R.drawable.icon_minus : R.drawable.icon_plus); } else { holder.icon.setImageResource(R.drawable.icon_node); } return convertView; } private int getLevel(TreeNode node) { int level = 0; while (node.getParentId() != 0) { level++; node = findNodeById(node.getParentId()); } return level; } private boolean hasChildren(TreeNode node) { for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { return true; } } return false; } private TreeNode findNodeById(int nodeId) { for (TreeNode node : nodes) { if (node.getNodeId() == nodeId) { return node; } } return null; } static class ViewHolder { ImageView icon; TextView name; } } ``` 3. 初始化树形数据 ```java private void initTreeData() { nodes = new ArrayList<>(); nodes.add(new TreeNode(1, 0, "Node 1")); nodes.add(new TreeNode(2, 0, "Node 2")); nodes.add(new TreeNode(3, 1, "Node 1-1")); nodes.add(new TreeNode(4, 1, "Node 1-2")); nodes.add(new TreeNode(5, 3, "Node 1-1-1")); nodes.add(new TreeNode(6, 3, "Node 1-1-2")); nodes.add(new TreeNode(7, 4, "Node 1-2-1")); nodes.add(new TreeNode(8, 2, "Node 2-1")); nodes.add(new TreeNode(9, 2, "Node 2-2")); } ``` 4. 实现节点展开和折叠功能 ```java private void toggleNode(int position) { TreeNode node = nodes.get(position); if (node.isExpanded()) { collapseNode(node); } else { expandNode(node); } notifyDataSetChanged(); } private void expandNode(TreeNode node) { node.setExpanded(true); for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { n.setVisible(true); } } } private void collapseNode(TreeNode node) { node.setExpanded(false); for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { n.setVisible(false); collapseNode(n); } } } ``` 5. 监听节点点击事件 ```java listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { toggleNode(position); } }); ```
评论 78
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值