当前位置: 代码迷 >> Android >> Android增高十七篇之多级树形菜单的实现
  详细解决方案

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

热度:44   发布时间:2016-05-01 16:19:40.0
Android提高十七篇之多级树形菜单的实现

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

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

view plaincopy to clipboardprint?
  1. static?public?class?TreeNode{??
  2. ????Object?parent;??
  3. ????List<Object>?childs=new?ArrayList<Object>();??
  4. }??

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

view plaincopy to clipboardprint?
  1. static?public?class?SuperTreeNode?{??
  2. ????Object?parent;??
  3. ????//二级树形菜单的结构体??
  4. ????List<TreeViewAdapter.TreeNode>?childs?=?new?ArrayList<TreeViewAdapter.TreeNode>();??
  5. }??

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

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

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

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

main.xml源码如下:

view plaincopy to clipboardprint?
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:orientation="vertical"?android:layout_width="fill_parent"??
  4. ????android:layout_height="fill_parent">??
  5. ????<LinearLayout?android:id="@+id/LinearLayout01"??
  6. ????????android:layout_width="wrap_content"?android:layout_height="wrap_content">??
  7. ????????<Button?android:layout_height="wrap_content"?android:text="两层结构"??
  8. ????????????android:layout_width="160dip"?android:id="@+id/btnNormal"></Button>??
  9. ????????<Button?android:layout_height="wrap_content"?android:text="三层结构"??
  10. ????????????android:layout_width="160dip"?android:id="@+id/btnSuper"></Button>??
  11. ????</LinearLayout>??
  12. ????<ExpandableListView?android:id="@+id/ExpandableListView01"??
  13. ????????android:layout_width="fill_parent"?android:layout_height="fill_parent"></ExpandableListView>??
  14. </LinearLayout>??

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

view plaincopy to clipboardprint?
  1. package?com.testExpandableList;??
  2. ??
  3. ??
  4. import?java.util.List;??
  5. import?android.app.Activity;??
  6. import?android.os.Bundle;??
  7. import?android.util.Log;??
  8. import?android.view.View;??
  9. import?android.widget.Button;??
  10. import?android.widget.ExpandableListView;??
  11. import?android.widget.ExpandableListView.OnChildClickListener;??
  12. import?android.widget.Toast;??
  13. ??
  14. public?class?testExpandableList?extends?Activity?{??
  15. ????/**?Called?when?the?activity?is?first?created.?*/??
  16. ????ExpandableListView?expandableList;??
  17. ????TreeViewAdapter?adapter;??
  18. ????SuperTreeViewAdapter?superAdapter;??
  19. ????Button?btnNormal,btnSuper;??
  20. ????//?Sample?data?set.??children[i]?contains?the?children?(String[])?for?groups[i].??
  21. ????public?String[]?groups?=?{?"xxxx好友",?"xxxx同学",?"xxxxx女人"};??
  22. ????public?String[][]??child=?{??
  23. ????????????{?"A君",?"B君",?"C君",?"D君"?},??
  24. ????????????{?"同学甲",?"同学乙",?"同学丙"},??
  25. ????????????{?"御姐",?"萝莉"?}??
  26. ????};??
  27. ??????
  28. ????public?String[]?parent?=?{?"xxxx好友",?"xxxx同学"};??
  29. ????public?String[][][]??child_grandson=?{??
  30. ????????????{{"A君"},??
  31. ????????????????{"AA","AAA"}},??
  32. ????????????{{"B君"},??
  33. ????????????????{"BBB","BBBB","BBBBB"}},??
  34. ????????????{{"C君"},??
  35. ????????????????{"CCC","CCCC"}},??
  36. ????????????{{"D君"},??
  37. ????????????????{"DDD","DDDD","DDDDD"}},??
  38. ????};??
  39. ??????
  40. ????@Override??
  41. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  42. ????????super.onCreate(savedInstanceState);??
  43. ????????setContentView(R.layout.main);??
  44. ????????this.setTitle("ExpandableListView练习----hellogv");??
  45. ????????btnNormal=(Button)this.findViewById(R.id.btnNormal);??
  46. ????????btnNormal.setOnClickListener(new?ClickEvent());??
  47. ????????btnSuper=(Button)this.findViewById(R.id.btnSuper);??
  48. ????????btnSuper.setOnClickListener(new?ClickEvent());??
  49. ????????adapter=new?TreeViewAdapter(this,TreeViewAdapter.PaddingLeft>>1);??
  50. ????????superAdapter=new?SuperTreeViewAdapter(this,stvClickEvent);??
  51. ????????expandableList=(ExpandableListView)?testExpandableList.this.findViewById(R.id.ExpandableListView01);??
  52. ????}??
  53. ??????
  54. ????class?ClickEvent?implements?View.OnClickListener{??
  55. ??
  56. ????????@Override??
  57. ????????public?void?onClick(View?v)?{??
  58. ????????????adapter.RemoveAll();??
  59. ????????????adapter.notifyDataSetChanged();??
  60. ????????????superAdapter.RemoveAll();??
  61. ????????????superAdapter.notifyDataSetChanged();??
  62. ??????????????
  63. ????????????if(v==btnNormal)??
  64. ????????????{??
  65. ????????????????List<TreeViewAdapter.TreeNode>?treeNode?=?adapter.GetTreeNode();??
  66. ????????????????for(int?i=0;i<groups.length;i++)??
  67. ????????????????{??
  68. ????????????????????TreeViewAdapter.TreeNode?node=new?TreeViewAdapter.TreeNode();??
  69. ????????????????????node.parent=groups[i];??
  70. ????????????????????for(int?ii=0;ii<child[i].length;ii++)??
  71. ????????????????????{??
  72. ????????????????????????node.childs.add(child[i][ii]);??
  73. ????????????????????}??
  74. ????????????????????treeNode.add(node);??
  75. ????????????????}??
  76. ??????????????????
  77. ????????????????adapter.UpdateTreeNode(treeNode);???????
  78. ????????????????expandableList.setAdapter(adapter);??
  79. ????????????????expandableList.setOnChildClickListener(new?OnChildClickListener(){??
  80. ??
  81. ????????????????????@Override??
  82. ????????????????????public?boolean?onChildClick(ExpandableListView?arg0,?View?arg1,??
  83. ????????????????????????????int?parent,?int?children,?long?arg4)?{??
  84. ??????????????????????????
  85. ????????????????????????String?str="parent?id:"+String.valueOf(parent)+",children?id:"+String.valueOf(children);??
  86. ????????????????????????Toast.makeText(testExpandableList.this,?str,?300).show();??
  87. ????????????????????????return?false;??
  88. ????????????????????}??
  89. ????????????????});??
  90. ????????????}??
  91. ????????????else?if(v==btnSuper){??
  92. ????????????????List<SuperTreeViewAdapter.SuperTreeNode>?superTreeNode?=?superAdapter.GetTreeNode();??
  93. ????????????????for(int?i=0;i<parent.length;i++)//第一层??
  94. ????????????????{??
  95. ????????????????????SuperTreeViewAdapter.SuperTreeNode?superNode=new?SuperTreeViewAdapter.SuperTreeNode();??
  96. ????????????????????superNode.parent=parent[i];??
  97. ??????????????????????
  98. ????????????????????//第二层??
  99. ????????????????????for(int?ii=0;ii<child_grandson.length;ii++)??
  100. ????????????????????{??
  101. ????????????????????????TreeViewAdapter.TreeNode?node=new?TreeViewAdapter.TreeNode();??
  102. ????????????????????????node.parent=child_grandson[ii][0][0];//第二级菜单的标题??
  103. ??????????????????????????
  104. ????????????????????????for(int?iii=0;iii<child_grandson[ii][1].length;iii++)//第三级菜单??
  105. ????????????????????????{??
  106. ????????????????????????????node.childs.add(child_grandson[ii][1][iii]);??
  107. ????????????????????????}??
  108. ????????????????????????superNode.childs.add(node);??
  109. ????????????????????}??
  110. ????????????????????superTreeNode.add(superNode);??
  111. ??????????????????????
  112. ????????????????}??
  113. ????????????????superAdapter.UpdateTreeNode(superTreeNode);??
  114. ????????????????expandableList.setAdapter(superAdapter);??
  115. ????????????}??
  116. ????????}??
  117. ????}??
  118. ??
  119. ????/**?
  120. ?????*?三级树形菜单的事件不再可用,本函数由三级树形菜单的子项(二级菜单)进行回调?
  121. ?????*/??
  122. ????OnChildClickListener?stvClickEvent=new?OnChildClickListener(){??
  123. ??
  124. ????????@Override??
  125. ????????public?boolean?onChildClick(ExpandableListView?parent,??
  126. ????????????????View?v,?int?groupPosition,?int?childPosition,??
  127. ????????????????long?id)?{??
  128. ????????????String?str="parent?id:"+String.valueOf(groupPosition)+",children?id:"+String.valueOf(childPosition);??
  129. ????????????Toast.makeText(testExpandableList.this,?str,?300).show();??
  130. ??????????????
  131. ????????????return?false;??
  132. ????????}??
  133. ??????????
  134. ????};??
  135. }??

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

view plaincopy to clipboardprint?
  1. package?com.testExpandableList;??
  2. ??
  3. import?java.util.ArrayList;??
  4. import?java.util.List;??
  5. import?android.content.Context;??
  6. import?android.util.Log;??
  7. import?android.view.Gravity;??
  8. import?android.view.View;??
  9. import?android.view.ViewGroup;??
  10. import?android.widget.AbsListView;??
  11. import?android.widget.BaseExpandableListAdapter;??
  12. import?android.widget.TextView;??
  13. ??
  14. ??
  15. public?class?TreeViewAdapter?extends?BaseExpandableListAdapter{??
  16. ????public?static?final?int?ItemHeight=48;//每项的高度??
  17. ????public?static?final?int?PaddingLeft=36;//每项的高度??
  18. ????private?int?myPaddingLeft=0;//如果是由SuperTreeView调用,则作为子项需要往右移??
  19. ??
  20. ????static?public?class?TreeNode{??
  21. ????????Object?parent;??
  22. ????????List<Object>?childs=new?ArrayList<Object>();??
  23. ????}??
  24. ??????
  25. ????List<TreeNode>?treeNodes?=?new?ArrayList<TreeNode>();??
  26. ????Context?parentContext;??
  27. ??????
  28. ????public?TreeViewAdapter(Context?view,int?myPaddingLeft)??
  29. ????{??
  30. ????????parentContext=view;??
  31. ????????this.myPaddingLeft=myPaddingLeft;??
  32. ????}??
  33. ??????
  34. ????public?List<TreeNode>?GetTreeNode()??
  35. ????{??
  36. ????????return?treeNodes;??
  37. ????}??
  38. ??????
  39. ????public?void?UpdateTreeNode(List<TreeNode>?nodes)??
  40. ????{??
  41. ????????treeNodes=nodes;??
  42. ????}??
  43. ??????
  44. ????public?void?RemoveAll()??
  45. ????{??
  46. ????????treeNodes.clear();??
  47. ????}??
  48. ??????
  49. ????public?Object?getChild(int?groupPosition,?int?childPosition)?{??
  50. ????????return?treeNodes.get(groupPosition).childs.get(childPosition);??
  51. ????}??
  52. ??
  53. ????public?int?getChildrenCount(int?groupPosition)?{??
  54. ????????return?treeNodes.get(groupPosition).childs.size();??
  55. ????}??
  56. ??
  57. ????static?public?TextView?getTextView(Context?context)?{??
  58. ????????AbsListView.LayoutParams?lp?=?new?AbsListView.LayoutParams(??
  59. ????????????????ViewGroup.LayoutParams.FILL_PARENT,?ItemHeight);??
  60. ??
  61. ????????TextView?textView?=?new?TextView(context);??
  62. ????????textView.setLayoutParams(lp);??
  63. ????????textView.setGravity(Gravity.CENTER_VERTICAL?|?Gravity.LEFT);??
  64. ????????return?textView;??
  65. ????}??
  66. ??
  67. ????public?View?getChildView(int?groupPosition,?int?childPosition,??
  68. ????????????boolean?isLastChild,?View?convertView,?ViewGroup?parent)?{??
  69. ????????TextView?textView?=?getTextView(this.parentContext);??
  70. ????????textView.setText(getChild(groupPosition,?childPosition).toString());??
  71. ????????textView.setPadding(myPaddingLeft+PaddingLeft,?0,?0,?0);??
  72. ????????return?textView;??
  73. ????}??
  74. ??
  75. ????public?View?getGroupView(int?groupPosition,?boolean?isExpanded,??
  76. ????????????View?convertView,?ViewGroup?parent)?{??
  77. ????????TextView?textView?=?getTextView(this.parentContext);??
  78. ????????textView.setText(getGroup(groupPosition).toString());??
  79. ????????textView.setPadding(myPaddingLeft+(PaddingLeft>>1),?0,?0,?0);??
  80. ????????return?textView;??
  81. ????}??
  82. ??
  83. ????public?long?getChildId(int?groupPosition,?int?childPosition)?{??
  84. ????????return?childPosition;??
  85. ????}??
  86. ??
  87. ????public?Object?getGroup(int?groupPosition)?{??
  88. ????????return?treeNodes.get(groupPosition).parent;??
  89. ????}??
  90. ??
  91. ????public?int?getGroupCount()?{??
  92. ????????return?treeNodes.size();??
  93. ????}??
  94. ??
  95. ????public?long?getGroupId(int?groupPosition)?{??
  96. ????????return?groupPosition;??
  97. ????}??
  98. ??
  99. ????public?boolean?isChildSelectable(int?groupPosition,?int?childPosition)?{??
  100. ????????return?true;??
  101. ????}??
  102. ??
  103. ????public?boolean?hasStableIds()?{??
  104. ????????return?true;??
  105. ????}??
  106. }??

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

view plaincopy to clipboardprint?
  1. package?com.testExpandableList;??
  2. ??
  3. import?java.util.ArrayList;??
  4. import?java.util.List;??
  5. import?com.testExpandableList.TreeViewAdapter.TreeNode;??
  6. import?android.content.Context;??
  7. import?android.view.View;??
  8. import?android.view.ViewGroup;??
  9. import?android.widget.AbsListView;??
  10. import?android.widget.BaseExpandableListAdapter;??
  11. import?android.widget.ExpandableListView;??
  12. import?android.widget.ExpandableListView.OnChildClickListener;??
  13. import?android.widget.ExpandableListView.OnGroupCollapseListener;??
  14. import?android.widget.ExpandableListView.OnGroupExpandListener;??
  15. import?android.widget.TextView;??
  16. ??
  17. public?class?SuperTreeViewAdapter?extends?BaseExpandableListAdapter?{??
  18. ??
  19. ????static?public?class?SuperTreeNode?{??
  20. ????????Object?parent;??
  21. ????????//二级树形菜单的结构体??
  22. ????????List<TreeViewAdapter.TreeNode>?childs?=?new?ArrayList<TreeViewAdapter.TreeNode>();??
  23. ????}??
  24. ??
  25. ????private?List<SuperTreeNode>?superTreeNodes?=?new?ArrayList<SuperTreeNode>();??
  26. ????private?Context?parentContext;??
  27. ????private?OnChildClickListener?stvClickEvent;//外部回调函数??
  28. ??????
  29. ????public?SuperTreeViewAdapter(Context?view,OnChildClickListener?stvClickEvent)?{??
  30. ????????parentContext?=?view;??
  31. ????????this.stvClickEvent=stvClickEvent;??
  32. ????}??
  33. ??
  34. ????public?List<SuperTreeNode>?GetTreeNode()?{??
  35. ????????return?superTreeNodes;??
  36. ????}??
  37. ??
  38. ????public?void?UpdateTreeNode(List<SuperTreeNode>?node)?{??
  39. ????????superTreeNodes?=?node;??
  40. ????}??
  41. ??????
  42. ????public?void?RemoveAll()??
  43. ????{??
  44. ????????superTreeNodes.clear();??
  45. ????}??
  46. ??????
  47. ????public?Object?getChild(int?groupPosition,?int?childPosition)?{??
  48. ????????return?superTreeNodes.get(groupPosition).childs.get(childPosition);??
  49. ????}??
  50. ??
  51. ????public?int?getChildrenCount(int?groupPosition)?{??
  52. ????????return?superTreeNodes.get(groupPosition).childs.size();??
  53. ????}??
  54. ??
  55. ????public?ExpandableListView?getExpandableListView()?{??
  56. ????????AbsListView.LayoutParams?lp?=?new?AbsListView.LayoutParams(??
  57. ????????????????ViewGroup.LayoutParams.FILL_PARENT,?TreeViewAdapter.ItemHeight);??
  58. ????????ExpandableListView?superTreeView?=?new?ExpandableListView(parentContext);??
  59. ????????superTreeView.setLayoutParams(lp);??
  60. ????????return?superTreeView;??
  61. ????}??
  62. ??
  63. ????/**?
  64. ?????*?三层树结构中的第二层是一个ExpandableListView?
  65. ?????*/???
  66. ????public?View?getChildView(int?groupPosition,?int?childPosition,??
  67. ????????????boolean?isLastChild,?View?convertView,?ViewGroup?parent)?{??
  68. ????????//?是???
  69. ????????final?ExpandableListView?treeView?=?getExpandableListView();??
  70. ????????final?TreeViewAdapter?treeViewAdapter?=?new?TreeViewAdapter(this.parentContext,0);??
  71. ????????List<TreeNode>?tmp?=?treeViewAdapter.GetTreeNode();//临时变量取得TreeViewAdapter的TreeNode集合,可为空??
  72. ????????final?TreeNode?treeNode=(TreeNode)?getChild(groupPosition,?childPosition);??
  73. ????????tmp.add(treeNode);??
  74. ????????treeViewAdapter.UpdateTreeNode(tmp);??
  75. ????????treeView.setAdapter(treeViewAdapter);??
  76. ??????????
  77. ????????//关键点:取得选中的二级树形菜单的父子节点,结果返回给外部回调函数??
  78. ????????treeView.setOnChildClickListener(this.stvClickEvent);??
  79. ??????????
  80. ????????/**?
  81. ?????????*?关键点:第二级菜单展开时通过取得节点数来设置第三级菜单的大小?
  82. ?????????*/??
  83. ????????treeView.setOnGroupExpandListener(new?OnGroupExpandListener()?{??
  84. ????????????@Override??
  85. ????????????public?void?onGroupExpand(int?groupPosition)?{??
  86. ??????????????????
  87. ????????????????AbsListView.LayoutParams?lp?=?new?AbsListView.LayoutParams(??
  88. ????????????????????????ViewGroup.LayoutParams.FILL_PARENT,??
  89. ????????????????????????(treeNode.childs.size()+1)*TreeViewAdapter.ItemHeight?+?10);??
  90. ????????????????treeView.setLayoutParams(lp);??
  91. ????????????}??
  92. ????????});??
  93. ??????????
  94. ????????/**?
  95. ?????????*?第二级菜单回收时设置为标准Item大小?
  96. ?????????*/??
  97. ????????treeView.setOnGroupCollapseListener(new?OnGroupCollapseListener()?{??
  98. ????????????@Override??
  99. ????????????public?void?onGroupCollapse(int?groupPosition)?{??
  100. ??????????????????
  101. ????????????????AbsListView.LayoutParams?lp?=?new?AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,??
  102. ????????????????????????TreeViewAdapter.ItemHeight);??
  103. ????????????????treeView.setLayoutParams(lp);??
  104. ????????????}??
  105. ????????});??
  106. ????????treeView.setPadding(TreeViewAdapter.PaddingLeft,?0,?0,?0);??
  107. ????????return?treeView;??
  108. ????}??
  109. ??
  110. ????/**?
  111. ?????*?三级树结构中的首层是TextView,用于作为title?
  112. ?????*/??
  113. ????public?View?getGroupView(int?groupPosition,?boolean?isExpanded,??
  114. ????????????View?convertView,?ViewGroup?parent)?{??
  115. ????????TextView?textView?=?TreeViewAdapter.getTextView(this.parentContext);??
  116. ????????textView.setText(getGroup(groupPosition).toString());??
  117. ????????textView.setPadding(TreeViewAdapter.PaddingLeft,?0,?0,?0);??
  118. ????????return?textView;??
  119. ????}??
  120. ??
  121. ????public?long?getChildId(int?groupPosition,?int?childPosition)?{??
  122. ????????return?childPosition;??
  123. ????}??
  124. ??
  125. ????public?Object?getGroup(int?groupPosition)?{??
  126. ????????return?superTreeNodes.get(groupPosition).parent;??
  127. ????}??
  128. ??
  相关解决方案