本文来自http://blog.csdn.net/hellogv/,引用必须注明出处!
在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。本文程序运行效果图:
当用BaseExpandableListAdapter来实现二级树形菜单时,父项(getGroupView())和子项(getChildView())都是使用TextView。当要实现三级树形菜单时,子项(getChildView())就必须使用ExpandableList了.......另外还要定义结构体来方便调用三级树形的数据,二级树形菜单可以用如下:
-
staticpublicclassTreeNode{
-
Objectparent;
-
List<Object>childs=newArrayList<Object>();
-
}
三级树形菜单可以用如下,子项是二级树形菜单的结构体:
-
staticpublicclassSuperTreeNode{
-
Objectparent;
-
-
List<TreeViewAdapter.TreeNode>childs=newArrayList<TreeViewAdapter.TreeNode>();
-
}
实现三级树形菜单有两点要注意的:
1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;
2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。
PS:本文在解决No.2关键点的时候,只能取得第三级选中的序号.....而第一,第二级依然无法获取其序号。
main.xml源码如下:
-
<?xmlversion="1.0"encoding="utf-8"?>
-
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
android:orientation="vertical"android:layout_width="fill_parent"
-
android:layout_height="fill_parent">
-
<LinearLayoutandroid:id="@+id/LinearLayout01"
-
android:layout_width="wrap_content"android:layout_height="wrap_content">
-
<Buttonandroid:layout_height="wrap_content"android:text="两层结构"
-
android:layout_width="160dip"android:id="@+id/btnNormal"></Button>
-
<Buttonandroid:layout_height="wrap_content"android:text="三层结构"
-
android:layout_width="160dip"android:id="@+id/btnSuper"></Button>
-
</LinearLayout>
-
<ExpandableListViewandroid:id="@+id/ExpandableListView01"
-
android:layout_width="fill_parent"android:layout_height="fill_parent"></ExpandableListView>
-
</LinearLayout>
testExpandableList.java是主类,调用其他工具类,源码如下:
-
packagecom.testExpandableList;
-
-
-
importjava.util.List;
-
importandroid.app.Activity;
-
importandroid.os.Bundle;
-
importandroid.util.Log;
-
importandroid.view.View;
-
importandroid.widget.Button;
-
importandroid.widget.ExpandableListView;
-
importandroid.widget.ExpandableListView.OnChildClickListener;
-
importandroid.widget.Toast;
-
-
publicclasstestExpandableListextendsActivity{
-
-
ExpandableListViewexpandableList;
-
TreeViewAdapteradapter;
-
SuperTreeViewAdaptersuperAdapter;
-
ButtonbtnNormal,btnSuper;
-
-
publicString[]groups={"xxxx好友","xxxx同学","xxxxx女人"};
-
publicString[][]child={
-
{"A君","B君","C君","D君"},
-
{"同学甲","同学乙","同学丙"},
-
{"御姐","萝莉"}
-
};
-
-
publicString[]parent={"xxxx好友","xxxx同学"};
-
publicString[][][]child_grandson={
-
{{"A君"},
-
{"AA","AAA"}},
-
{{"B君"},
-
{"BBB","BBBB","BBBBB"}},
-
{{"C君"},
-
{"CCC","CCCC"}},
-
{{"D君"},
-
{"DDD","DDDD","DDDDD"}},
-
};
-
-
@Override
-
publicvoidonCreate(BundlesavedInstanceState){
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
this.setTitle("ExpandableListView练习----hellogv");
-
btnNormal=(Button)this.findViewById(R.id.btnNormal);
-
btnNormal.setOnClickListener(newClickEvent());
-
btnSuper=(Button)this.findViewById(R.id.btnSuper);
-
btnSuper.setOnClickListener(newClickEvent());
-
adapter=newTreeViewAdapter(this,TreeViewAdapter.PaddingLeft>>1);
-
superAdapter=newSuperTreeViewAdapter(this,stvClickEvent);
-
expandableList=(ExpandableListView)testExpandableList.this.findViewById(R.id.ExpandableListView01);
-
}
-
-
classClickEventimplementsView.OnClickListener{
-
-
@Override
-
publicvoidonClick(Viewv){
-
adapter.RemoveAll();
-
adapter.notifyDataSetChanged();
-
superAdapter.RemoveAll();
-
superAdapter.notifyDataSetChanged();
-
-
if(v==btnNormal)
-
{
-
List<TreeViewAdapter.TreeNode>treeNode=adapter.GetTreeNode();
-
for(inti=0;i<groups.length;i++)
-
{
-
TreeViewAdapter.TreeNodenode=newTreeViewAdapter.TreeNode();
-
node.parent=groups[i];
-
for(intii=0;ii<child[i].length;ii++)
-
{
-
node.childs.add(child[i][ii]);
-
}
-
treeNode.add(node);
-
}
-
-
adapter.UpdateTreeNode(treeNode);
-
expandableList.setAdapter(adapter);
-
expandableList.setOnChildClickListener(newOnChildClickListener(){
-
-
@Override
-
publicbooleanonChildClick(ExpandableListViewarg0,Viewarg1,
-
intparent,intchildren,longarg4){
-
-
Stringstr="parentid:"+String.valueOf(parent)+",childrenid:"+String.valueOf(children);
-
Toast.makeText(testExpandableList.this,str,300).show();
-
returnfalse;
-
}
-
});
-
}
-
elseif(v==btnSuper){
-
List<SuperTreeViewAdapter.SuperTreeNode>superTreeNode=superAdapter.GetTreeNode();
-
for(inti=0;i<parent.length;i++)
-
{
-
SuperTreeViewAdapter.SuperTreeNodesuperNode=newSuperTreeViewAdapter.SuperTreeNode();
-
superNode.parent=parent[i];
-
-
-
for(intii=0;ii<child_grandson.length;ii++)
-
{
-
TreeViewAdapter.TreeNodenode=newTreeViewAdapter.TreeNode();
-
node.parent=child_grandson[ii][0][0];
-
-
for(intiii=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);
-
}
-
}
-
}
-
-
-
-
-
OnChildClickListenerstvClickEvent=newOnChildClickListener(){
-
-
@Override
-
publicbooleanonChildClick(ExpandableListViewparent,
-
Viewv,intgroupPosition,intchildPosition,
-
longid){
-
Stringstr="parentid:"+String.valueOf(groupPosition)+",childrenid:"+String.valueOf(childPosition);
-
Toast.makeText(testExpandableList.this,str,300).show();
-
-
returnfalse;
-
}
-
-
};
-
}
TreeViewAdapter.java是实现二级树形菜单的工具类,源码如下:
-
packagecom.testExpandableList;
-
-
importjava.util.ArrayList;
-
importjava.util.List;
-
importandroid.content.Context;
-
importandroid.util.Log;
-
importandroid.view.Gravity;
-
importandroid.view.View;
-
importandroid.view.ViewGroup;
-
importandroid.widget.AbsListView;
-
importandroid.widget.BaseExpandableListAdapter;
-
importandroid.widget.TextView;
-
-
-
publicclassTreeViewAdapterextendsBaseExpandableListAdapter{
-
publicstaticfinalintItemHeight=48;
-
publicstaticfinalintPaddingLeft=36;
-
privateintmyPaddingLeft=0;
-
-
staticpublicclassTreeNode{
-
Objectparent;
-
List<Object>childs=newArrayList<Object>();
-
}
-
-
List<TreeNode>treeNodes=newArrayList<TreeNode>();
-
ContextparentContext;
-
-
publicTreeViewAdapter(Contextview,intmyPaddingLeft)
-
{
-
parentContext=view;
-
this.myPaddingLeft=myPaddingLeft;
-
}
-
-
publicList<TreeNode>GetTreeNode()
-
{
-
returntreeNodes;
-
}
-
-
publicvoidUpdateTreeNode(List<TreeNode>nodes)
-
{
-
treeNodes=nodes;
-
}
-
-
publicvoidRemoveAll()
-
{
-
treeNodes.clear();
-
}
-
-
publicObjectgetChild(intgroupPosition,intchildPosition){
-
returntreeNodes.get(groupPosition).childs.get(childPosition);
-
}
-
-
publicintgetChildrenCount(intgroupPosition){
-
returntreeNodes.get(groupPosition).childs.size();
-
}
-
-
staticpublicTextViewgetTextView(Contextcontext){
-
AbsListView.LayoutParamslp=newAbsListView.LayoutParams(
-
ViewGroup.LayoutParams.FILL_PARENT,ItemHeight);
-
-
TextViewtextView=newTextView(context);
-
textView.setLayoutParams(lp);
-
textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);
-
returntextView;
-
}
-
-
publicViewgetChildView(intgroupPosition,intchildPosition,
-
booleanisLastChild,ViewconvertView,ViewGroupparent){
-
TextViewtextView=getTextView(this.parentContext);
-
textView.setText(getChild(groupPosition,childPosition).toString());
-
textView.setPadding(myPaddingLeft+PaddingLeft,0,0,0);
-
returntextView;
-
}
-
-
publicViewgetGroupView(intgroupPosition,booleanisExpanded,
-
ViewconvertView,ViewGroupparent){
-
TextViewtextView=getTextView(this.parentContext);
-
textView.setText(getGroup(groupPosition).toString());
-
textView.setPadding(myPaddingLeft+(PaddingLeft>>1),0,0,0);
-
returntextView;
-
}
-
-
publiclonggetChildId(intgroupPosition,intchildPosition){
-
returnchildPosition;
-
}
-
-
publicObjectgetGroup(intgroupPosition){
-
returntreeNodes.get(groupPosition).parent;
-
}
-
-
publicintgetGroupCount(){
-
returntreeNodes.size();
-
}
-
-
publiclonggetGroupId(intgroupPosition){
-
returngroupPosition;
-
}
-
-
publicbooleanisChildSelectable(intgroupPosition,intchildPosition){
-
returntrue;
-
}
-
-
publicbooleanhasStableIds(){
-
returntrue;
-
}
-
}
SuperTreeViewAdapter.java是实现三级树形菜单的工具类,会用到TreeViewAdapter.java,源码如下:
-
packagecom.testExpandableList;
-
-
importjava.util.ArrayList;
-
importjava.util.List;
-
importcom.testExpandableList.TreeViewAdapter.TreeNode;
-
importandroid.content.Context;
-
importandroid.view.View;
-
importandroid.view.ViewGroup;
-
importandroid.widget.AbsListView;
-
importandroid.widget.BaseExpandableListAdapter;
-
importandroid.widget.ExpandableListView;
-
importandroid.widget.ExpandableListView.OnChildClickListener;
-
importandroid.widget.ExpandableListView.OnGroupCollapseListener;
-
importandroid.widget.ExpandableListView.OnGroupExpandListener;
-
importandroid.widget.TextView;
-
-
publicclassSuperTreeViewAdapterextendsBaseExpandableListAdapter{
-
-
staticpublicclassSuperTreeNode{
-
Objectparent;
-
-
List<TreeViewAdapter.TreeNode>childs=newArrayList<TreeViewAdapter.TreeNode>();
-
}
-
-
privateList<SuperTreeNode>superTreeNodes=newArrayList<SuperTreeNode>();
-
privateContextparentContext;
-
privateOnChildClickListenerstvClickEvent;
-
-
publicSuperTreeViewAdapter(Contextview,OnChildClickListenerstvClickEvent){
-
parentContext=view;
-
this.stvClickEvent=stvClickEvent;
-
}
-
-
publicList<SuperTreeNode>GetTreeNode(){
-
returnsuperTreeNodes;
-
}
-
-
publicvoidUpdateTreeNode(List<SuperTreeNode>node){
-
superTreeNodes=node;
-
}
-
-
publicvoidRemoveAll()
-
{
-
superTreeNodes.clear();
-
}
-
-
publicObjectgetChild(intgroupPosition,intchildPosition){
-
returnsuperTreeNodes.get(groupPosition).childs.get(childPosition);
-
}
-
-
publicintgetChildrenCount(intgroupPosition){
-
returnsuperTreeNodes.get(groupPosition).childs.size();
-
}
-
-
publicExpandableListViewgetExpandableListView(){
-
AbsListView.LayoutParamslp=newAbsListView.LayoutParams(
-
ViewGroup.LayoutParams.FILL_PARENT,TreeViewAdapter.ItemHeight);
-
ExpandableListViewsuperTreeView=newExpandableListView(parentContext);
-
superTreeView.setLayoutParams(lp);
-
returnsuperTreeView;
-
}
-
-
-
-
-
publicViewgetChildView(intgroupPosition,intchildPosition,
-
booleanisLastChild,ViewconvertView,ViewGroupparent){
-
-
finalExpandableListViewtreeView=getExpandableListView();
-
finalTreeViewAdaptertreeViewAdapter=newTreeViewAdapter(this.parentContext,0);
-
List<TreeNode>tmp=treeViewAdapter.GetTreeNode();
-
finalTreeNodetreeNode=(TreeNode)getChild(groupPosition,childPosition);
-
tmp.add(treeNode);
-
treeViewAdapter.UpdateTreeNode(tmp);
-
treeView.setAdapter(treeViewAdapter);
-
-
-
treeView.setOnChildClickListener(this.stvClickEvent);
-
-
-
-
-
treeView.setOnGroupExpandListener(newOnGroupExpandListener(){
-
@Override
-
publicvoidonGroupExpand(intgroupPosition){
-
-
AbsListView.LayoutParamslp=newAbsListView.LayoutParams(
-
ViewGroup.LayoutParams.FILL_PARENT,
-
(treeNode.childs.size()+1)*TreeViewAdapter.ItemHeight+10);
-
treeView.setLayoutParams(lp);
-
}
-
});
-
-
-
-
-
treeView.setOnGroupCollapseListener(newOnGroupCollapseListener(){
-
@Override
-
publicvoidonGroupCollapse(intgroupPosition){
-
-
AbsListView.LayoutParamslp=newAbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
-
TreeViewAdapter.ItemHeight);
-
treeView.setLayoutParams(lp);
-
}
-
});
-
treeView.setPadding(TreeViewAdapter.PaddingLeft,0,0,0);
-
returntreeView;
-
}
-
-
-
-
-
publicViewgetGroupView(intgroupPosition,booleanisExpanded,
-
ViewconvertView,ViewGroupparent){
-
TextViewtextView=TreeViewAdapter.getTextView(this.parentContext);
-
textView.setText(getGroup(groupPosition).toString());
-
textView.setPadding(TreeViewAdapter.PaddingLeft,0,0,0);
-
returntextView;
-
}
-
-
publiclonggetChildId(intgroupPosition,intchildPosition){
-
returnchildPosition;
-
}
-
-
publicObjectgetGroup(intgroupPosition){
-
returnsuperTreeNodes.get(groupPosition).parent;
-
}
-
-
publicintgetGroupCount(){
-
returnsuperTreeNodes.size();
-
}
-
-
publiclonggetGroupId(intgroupPosition){
-
returngroupPosition;
-
}
-
-
publicbooleanisChildSelectable(intgroupPosition,intchildPosition){
-
returntrue;
-
}
-
-
publicbooleanhasStableIds(){
-
returntrue;
-
}
-
}
总结,使用ExpandableList实现三级树形菜单时有些bug不好解决,而且定义三维数组的时候也要倍加小心......所以尽量把数据化简来使用二级树形菜单。
分享到:
相关推荐
Android Recyclerview实现多级树形列表
NULL 博文链接:https://haiyang08101.iteye.com/blog/1559388
在android 中实现左边树形菜单,右边展开节点,类似美团网、大众点评网一样的,源码
树形菜单,用来展示有层次结构的数据,像文件管理器,一个文件夹下面有很多文件,文件夹,可能文件夹下面还有文件还有文件夹。我们需要展示这些结构,但是安卓并没有提供一个比较方便的控件来展示,所以就需要我们...
一般来说在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单。本文所述实例也依然使用ExpandableList,但是要实现的是3...
在android设置上实现多级树形列表菜单,支持无限极列表,完美实现多级联动
多级树形选择列表,最近项目需求做一个android 多级树形选择列表,网上发现比较好的项目,分享一下
Android listview多级树形列表菜单,支持全选/反选功能,根据ID和组ID添加分支或叶节点
无限级数的属性菜单,并且支持多选功能
Android ExpandableListView双层嵌套实现三级树形菜单
一个RecyclerView,无限层级展示,不嵌套,高性能,企业级产品
主要为大家详细介绍了Android实现多级树形菜单并支持多选功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
仿淘宝,京东手机多级菜单效果,Android-树形(多级)菜单效果,
QML 中没有直接提供类似 android 的ExpandableListView二级列表控件,treeView,但是用 treeView 实在是有些不方便,并且达不到想要的效果,所以干脆用 ListView 来扩展一个。
主要介绍了Android UI 之实现多级列表TreeView示例,TreeView就是在Windows中常见的多级列表树,有兴趣的可以了解一下。
见卡普博客listview多级菜单,对应源码