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

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

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

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

static public class TreeNode{ Object parent; List<Object> childs=new ArrayList<Object>(); }

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

static public class SuperTreeNode { Object parent; //二级树形菜单的结构体 List<TreeViewAdapter.TreeNode> childs = new ArrayList<TreeViewAdapter.TreeNode>(); }

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

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

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

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

main.xml源码如下:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:text="两层结构" android:layout_width="160dip" android:id="@+id/btnNormal"></Button> <Button android:layout_height="wrap_content" android:text="三层结构" android:layout_width="160dip" android:id="@+id/btnSuper"></Button> </LinearLayout> <ExpandableListView android:id="@+id/ExpandableListView01" android:layout_width="fill_parent" android:layout_height="fill_parent"></ExpandableListView> </LinearLayout>

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

package com.testExpandableList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.Toast; public class testExpandableList extends Activity { /** Called when the activity is first created. */ ExpandableListView expandableList; TreeViewAdapter adapter; SuperTreeViewAdapter superAdapter; Button btnNormal,btnSuper; // Sample data set. children[i] contains the children (String[]) for groups[i]. public String[] groups = { "xxxx好友", "xxxx同学", "xxxxx女人"}; public String[][] child= { { "A君", "B君", "C君", "D君" }, { "同学甲", "同学乙", "同学丙"}, { "御姐", "萝莉" } }; public String[] parent = { "xxxx好友", "xxxx同学"}; public String[][][] child_grandson= { {{"A君"}, {"AA","AAA"}}, {{"B君"}, {"BBB","BBBB","BBBBB"}}, {{"C君"}, {"CCC","CCCC"}}, {{"D君"}, {"DDD","DDDD","DDDDD"}}, }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.setTitle("ExpandableListView练习----hellogv"); btnNormal=(Button)this.findViewById(R.id.btnNormal); btnNormal.setOnClickListener(new ClickEvent()); btnSuper=(Button)this.findViewById(R.id.btnSuper); btnSuper.setOnClickListener(new ClickEvent()); adapter=new TreeViewAdapter(this,TreeViewAdapter.PaddingLeft>>1); superAdapter=new SuperTreeViewAdapter(this,stvClickEvent); expandableList=(ExpandableListView) testExpandableList.this.findViewById(R.id.ExpandableListView01); } class ClickEvent implements View.OnClickListener{ @Override public void onClick(View v) { adapter.RemoveAll(); adapter.notifyDataSetChanged(); superAdapter.RemoveAll(); superAdapter.notifyDataSetChanged(); if(v==btnNormal) { List<TreeViewAdapter.TreeNode> treeNode = adapter.GetTreeNode(); for(int i=0;i<groups.length;i++) { TreeViewAdapter.TreeNode node=new TreeViewAdapter.TreeNode(); node.parent=groups[i]; for(int ii=0;ii<child[i].length;ii++) { node.childs.add(child[i][ii]); } treeNode.add(node); } adapter.UpdateTreeNode(treeNode); expandableList.setAdapter(adapter); expandableList.setOnChildClickListener(new OnChildClickListener(){ @Override public boolean onChildClick(ExpandableListView arg0, View arg1, int parent, int children, long arg4) { String str="parent id:"+String.valueOf(parent)+",children id:"+String.valueOf(children); Toast.makeText(testExpandableList.this, str, 300).show(); return false; } }); } else if(v==btnSuper){ List<SuperTreeViewAdapter.SuperTreeNode> superTreeNode = superAdapter.GetTreeNode(); for(int i=0;i<parent.length;i++)//第一层 { SuperTreeViewAdapter.SuperTreeNode superNode=new SuperTreeViewAdapter.SuperTreeNode(); superNode.parent=parent[i]; //第二层 for(int ii=0;ii<child_grandson.length;ii++) { TreeViewAdapter.TreeNode node=new TreeViewAdapter.TreeNode(); node.parent=child_grandson[ii][0][0];//第二级菜单的标题 for(int iii=0;iii<child_grandson[ii][1].length;iii++)//第三级菜单 { node.childs.add(child_grandson[ii][1][iii]); } superNode.childs.add(node); } superTreeNode.add(superNode); } superAdapter.UpdateTreeNode(superTreeNode); expandableList.setAdapter(superAdapter); } } } /** * 三级树形菜单的事件不再可用,本函数由三级树形菜单的子项(二级菜单)进行回调 */ OnChildClickListener stvClickEvent=new OnChildClickListener(){ @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { String str="parent id:"+String.valueOf(groupPosition)+",children id:"+String.valueOf(childPosition); Toast.makeText(testExpandableList.this, str, 300).show(); return false; } }; }

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

package com.testExpandableList; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; public class TreeViewAdapter extends BaseExpandableListAdapter{ public static final int ItemHeight=48;//每项的高度 public static final int PaddingLeft=36;//每项的高度 private int myPaddingLeft=0;//如果是由SuperTreeView调用,则作为子项需要往右移 static public class TreeNode{ Object parent; List<Object> childs=new ArrayList<Object>(); } List<TreeNode> treeNodes = new ArrayList<TreeNode>(); Context parentContext; public TreeViewAdapter(Context view,int myPaddingLeft) { parentContext=view; this.myPaddingLeft=myPaddingLeft; } public List<TreeNode> GetTreeNode() { return treeNodes; } public void UpdateTreeNode(List<TreeNode> nodes) { treeNodes=nodes; } public void RemoveAll() { treeNodes.clear(); } public Object getChild(int groupPosition, int childPosition) { return treeNodes.get(groupPosition).childs.get(childPosition); } public int getChildrenCount(int groupPosition) { return treeNodes.get(groupPosition).childs.size(); } static public TextView getTextView(Context context) { AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ItemHeight); TextView textView = new TextView(context); textView.setLayoutParams(lp); textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); return textView; } public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { TextView textView = getTextView(this.parentContext); textView.setText(getChild(groupPosition, childPosition).toString()); textView.setPadding(myPaddingLeft+PaddingLeft, 0, 0, 0); return textView; } public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { TextView textView = getTextView(this.parentContext); textView.setText(getGroup(groupPosition).toString()); textView.setPadding(myPaddingLeft+(PaddingLeft>>1), 0, 0, 0); return textView; } public long getChildId(int groupPosition, int childPosition) { return childPosition; } public Object getGroup(int groupPosition) { return treeNodes.get(groupPosition).parent; } public int getGroupCount() { return treeNodes.size(); } public long getGroupId(int groupPosition) { return groupPosition; } public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } public boolean hasStableIds() { return true; } }

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

package com.testExpandableList; import java.util.ArrayList; import java.util.List; import com.testExpandableList.TreeViewAdapter.TreeNode; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ExpandableListView.OnGroupCollapseListener; import android.widget.ExpandableListView.OnGroupExpandListener; import android.widget.TextView; public class SuperTreeViewAdapter extends BaseExpandableListAdapter { static public class SuperTreeNode { Object parent; //二级树形菜单的结构体 List<TreeViewAdapter.TreeNode> childs = new ArrayList<TreeViewAdapter.TreeNode>(); } private List<SuperTreeNode> superTreeNodes = new ArrayList<SuperTreeNode>(); private Context parentContext; private OnChildClickListener stvClickEvent;//外部回调函数 public SuperTreeViewAdapter(Context view,OnChildClickListener stvClickEvent) { parentContext = view; this.stvClickEvent=stvClickEvent; } public List<SuperTreeNode> GetTreeNode() { return superTreeNodes; } public void UpdateTreeNode(List<SuperTreeNode> node) { superTreeNodes = node; } public void RemoveAll() { superTreeNodes.clear(); } public Object getChild(int groupPosition, int childPosition) { return superTreeNodes.get(groupPosition).childs.get(childPosition); } public int getChildrenCount(int groupPosition) { return superTreeNodes.get(groupPosition).childs.size(); } public ExpandableListView getExpandableListView() { AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, TreeViewAdapter.ItemHeight); ExpandableListView superTreeView = new ExpandableListView(parentContext); superTreeView.setLayoutParams(lp); return superTreeView; } /** * 三层树结构中的第二层是一个ExpandableListView */ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // 是 final ExpandableListView treeView = getExpandableListView(); final TreeViewAdapter treeViewAdapter = new TreeViewAdapter(this.parentContext,0); List<TreeNode> tmp = treeViewAdapter.GetTreeNode();//临时变量取得TreeViewAdapter的TreeNode集合,可为空 final TreeNode treeNode=(TreeNode) getChild(groupPosition, childPosition); tmp.add(treeNode); treeViewAdapter.UpdateTreeNode(tmp); treeView.setAdapter(treeViewAdapter); //关键点:取得选中的二级树形菜单的父子节点,结果返回给外部回调函数 treeView.setOnChildClickListener(this.stvClickEvent); /** * 关键点:第二级菜单展开时通过取得节点数来设置第三级菜单的大小 */ treeView.setOnGroupExpandListener(new OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, (treeNode.childs.size()+1)*TreeViewAdapter.ItemHeight + 10); treeView.setLayoutParams(lp); } }); /** * 第二级菜单回收时设置为标准Item大小 */ treeView.setOnGroupCollapseListener(new OnGroupCollapseListener() { @Override public void onGroupCollapse(int groupPosition) { AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, TreeViewAdapter.ItemHeight); treeView.setLayoutParams(lp); } }); treeView.setPadding(TreeViewAdapter.PaddingLeft, 0, 0, 0); return treeView; } /** * 三级树结构中的首层是TextView,用于作为title */ public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { TextView textView = TreeViewAdapter.getTextView(this.parentContext); textView.setText(getGroup(groupPosition).toString()); textView.setPadding(TreeViewAdapter.PaddingLeft, 0, 0, 0); return textView; } public long getChildId(int groupPosition, int childPosition) { return childPosition; } public Object getGroup(int groupPosition) { return superTreeNodes.get(groupPosition).parent; } public int getGroupCount() { return superTreeNodes.size(); } public long getGroupId(int groupPosition) { return groupPosition; } public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } public boolean hasStableIds() { return true; } }

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

安卓多级树形列表(最大同时异步加载60万条数据) 该安卓多级树形列表是在前人的基础上做了大量的优化而诞生的,目前已经支持多级拓展,异步一次性最大加载量60万条不崩溃,点击秒展开,支持全选与单选,支持点击单列后再插入数据,支持数据联动 立即下载

相关推荐

Android代码-安卓任意层级树形菜单

Android任意层级树形菜单 免费视频课程传送门 【点击传送】 作者微博: @安卓攻城师sloop 实现过程: 1.将用户数据转化为node节点 2.设置节点之间的关联关系 3.排序 4.过滤需要显示的数据 涉及到的知识: 1.树形结构的数据组织 2.数据结构的进一步加强 3.反射 注解的使用(注解可以使用命名规范替代--可以提高一点效率) 4.封装与设计 截屏预览: About

115.Android 简单的多级树结构列表+正常列表结合使用(RecyclerView) 两种方式实现(自定义adapter实现和使用BaseQuickAdapter库实现)

initData();initData();//树结构布局//禁止滑动 布局管理器//禁止竖向滑动 RecyclerView 为垂直状态(VERTICAL)@Override//禁止横向滑动 RecyclerView 为水平状态(HORIZONTAL)}*///第一个参数 ListView & RecyclerView//第二个参数 上下文//第三个参数 数据集。

曹二少的博客 5084

如何优雅地进行频谱分析—— 一行代码实现绘制MATLAB频谱、功率谱图

之前的文章里讲了关于信号频谱、能量谱的相关理论和MATLAB编程实现方法: Mr.看海:信号频域分析方法的理解(频谱、能量谱、功率谱、倒频谱、小波分析) Mr.看海:频域特征值提取的MATLAB代码实现(频谱、功率谱、倒频谱) 不过对于刚刚开始进行这方面研究,或者对MATLAB不甚熟悉,抑或者不想花太多时间用在编程这件事上的同学,目前缺少一种足够便捷、高效、可靠的代码。 所以笔者想做这样一件事:编写一个函数,同学们只需要导入自己要分析的数据,并按照自己的需求设置部分选项,调用一行代码就可以实现绘制频

fengzhuqiaoqiu的博客 2万+

Android的自定义N级下拉菜单——ExpandableListiView&&ExpandListViewAdapter

Android的N级嵌套动态列表

weixin_46728351的博客 618

Unity3d实现红外热成像效果

1.将需要在红外图像中高亮的物体设置到图层PostProcessing。 2.新建一个相机CameraHighLight,设置其Culling Mask为PostProcessing,也就是在这个相机中只有PostProcessing图层的物体可见。 3.新建一个RenderTexture,命名为HightLightRt,将CameraHighLight的Target Texture设HightLightRt。 4.新建一个相机Camera2,这个相机用于显示其他物体。 接下来将CameraHigh

zouxin_88的专栏 8327

Modelsim安装教程以及管理员身份运行patch_dll.bat时找不到文件mgls.dll的解决

Modesim安装教程 Modesim版本有很多,但是安装方式大都相同,我们以modesim.10.5为例,电脑使用的是win10 64位,讲一下安装过程中的步骤以及出现问题的解决方法 一 安装 1.首先解压安装包,在解压的安装包内选择应用程序,右键选择管理员运行。 2.稍等一会,有的电脑会弹出是否允许modesim进行更改,选择 是 即可,然后出现下面的界面,点击下一步。 3.弹出此界面选择安装路径,选择安装路径,我是在D盘新建的文件夹,直接把文件夹中的路径复制在框内。文件夹名称切记不要带中文 4.

weixin_48564372的博客 1万+

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

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

jolfe的专栏 1036

百度智能云训练图像分割模型+python调用模型并分割图像

目录 训练模型阶段 发布图像分割API 调用图像分割API 创建应用后显示以下两个代码 在pycharm中可以调用API mask解码 依赖库pycocotools安装步骤: 依赖库urllib2的安装 源码下载: 最近上课听老师介绍了一个训练图像分割模型的网站,把数据集上传之后做图像标注,然后进行训练就能得到准确率等指标。 训练模型阶段 图像分割:https://ai.baidu.com/easydl/vision/ 图像分割-->创建模型-->上传数据--&gt

icecreamdinner的博客 1388
上一篇: 在Android上使用ZXing识别条形码/二维码
下一篇: Android入门第十六篇之Style与Theme
「已注销」
博客等级 码龄8年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值