生活随笔
收集整理的這篇文章主要介紹了
Android 多级树形菜单
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在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不好解決,而且定義三維數組的時候也要倍加小心......所以盡量把數據化簡來使用二級樹形菜單。
總結
以上是生活随笔為你收集整理的Android 多级树形菜单的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。