在 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;??
- ????}??
- ??
頂
踩
發表評論
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

評論