Android提高十七篇之多级树形菜单的实现
在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。本文程序运行效果图:
当用BaseExpandableListAdapter来实现二级树形菜单时,父项(getGroupView())和子项(getChildView())都是使用TextView。当要实现三级树形菜单时,子项(getChildView())就必须使用ExpandableList了.......另外还要定义结构体来方便调用三级树形的数据,二级树形菜单可以用如下:
view plaincopy to clipboardprint?
- static?public?class?TreeNode{??
- ????Object?parent;??
- ????List<Object>?childs=new?ArrayList<Object>();??
- }??
三级树形菜单可以用如下,子项是二级树形菜单的结构体:
view plaincopy to clipboardprint?
- static?public?class?SuperTreeNode?{??
- ????Object?parent;??
- ??????
- ????List<TreeViewAdapter.TreeNode>?childs?=?new?ArrayList<TreeViewAdapter.TreeNode>();??
- }??
实现三级树形菜单有两点要注意的:
1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;
2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。
PS:本文在解决No.2关键点的时候,只能取得第三级选中的序号.....而第一,第二级依然无法获取其序号。
main.xml源码如下:
view plaincopy to clipboardprint?
- <?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是主类,调用其他工具类,源码如下:
view plaincopy to clipboardprint?
- 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?{??
- ??????
- ????ExpandableListView?expandableList;??
- ????TreeViewAdapter?adapter;??
- ????SuperTreeViewAdapter?superAdapter;??
- ????Button?btnNormal,btnSuper;??
- ??????
- ????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是实现二级树形菜单的工具类,源码如下:
view plaincopy to clipboardprint?
- 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;??
- ??
- ????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,源码如下:
view plaincopy to clipboardprint?
- 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;??
- ????}??
- ??
- ?????
- ?
- ???
- ????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();??
- ????????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);??
- ????????????}??
- ????????});??
- ??????????
- ?????????
- ?
- ??
- ????????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;??
- ????}??
- ??
- ?????
- ?
- ??
- ????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;??
- ????}??
- ??
-