Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android提高21篇之十七:多級樹形菜單的實現

Android提高21篇之十七:多級樹形菜單的實現

編輯:關於android開發

       在Android裡要實現樹形菜單,都是用ExpandableList(也有高手自己繼承ListView或者LinearLayout來做),但是ExpandableList一般只能實現2級樹形菜單......本文也依然使用ExpandableList,但是要實現的是3級樹形菜單。本文程序運行效果圖:

Android提高21篇之十七:多級樹形菜單的實現

       當用BaseExpandableListAdapter來實現二級樹形菜單時,父項(getGroupView())和子項(getChildView())都是使用TextView。當要實現三級樹形菜單時,子項(getChildView())就必須使用ExpandableList了.......另外還要定義結構體來方便調用三級樹形的數據,二級樹形菜單可以用如下:

Java代碼
  1. static public class TreeNode{  
  2.                Object parent;  
  3.                List childs=new ArrayList();  
  4.        }  

       三級樹形菜單可以用如下,子項是二級樹形菜單的結構體:

Java代碼
  1. static public class SuperTreeNode {  
  2.                Object parent;  
  3.                //二級樹形菜單的結構體  
  4.                List[tr] childs = new ArrayList[tr]();  
  5.        }  

       實現三級樹形菜單有兩點要注意的:1、第二級也是個樹形菜單,因此必須在第二級項目展開/回收時設置足夠的空間來完全顯示二級樹形菜單;2、在實現三級樹形菜單時,發現菜單的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要獲得選中的數據就必須在外部定義好回調函數,然後在第二級生成二級樹形菜單時回調這個外部函數。PS:本文在解決No.2關鍵點的時候,只能取得第三級選中的序號.....而第一,第二級依然無法獲取其序號。main.xml源碼如下:

XML/HTML代碼
  1. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android"   
  2.         android:orientation="vertical" android:layout_width="fill_parent"  
  3.         android:layout_height="fill_parent">  
  4.         <linearlayout android:id="@+id/LinearLayout01"   
  5.                 android:layout_width="wrap_content" android:layout_height="wrap_content">  
  6.                 <button android:layout_height="wrap_content" android:text="兩層結構"   
  7.                         android:layout_width="160dip" android:id="@+id/btnNormal">  
  8.                 <button android:layout_height="wrap_content" android:text="三層結構"   
  9.                         android:layout_width="160dip" android:id="@+id/btnSuper">  
  10.           
  11.         <expandablelistview android:id="@+id/ExpandableListView01"   
  12.                 android:layout_width="fill_parent" android:layout_height="fill_parent">  

        testExpandableList.java是主類,調用其他工具類,源碼如下:

Java代碼
  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[tr] 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 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是實現二級樹形菜單的工具類,源碼如下:

Java代碼
  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 childs=new ArrayList();  
  23.         }  
  24.           
  25.         List[tr] treeNodes = new ArrayList[tr]();  
  26.         Context parentContext;  
  27.           
  28.         public TreeViewAdapter(Context view,int myPaddingLeft)  
  29.         {  
  30.                 parentContext=view;  
  31.                 this.myPaddingLeft=myPaddingLeft;  
  32.         }  
  33.           
  34.         public List[tr] GetTreeNode()  
  35.         {  
  36.                 return treeNodes;  
  37.         }  
  38.           
  39.         public void UpdateTreeNode(List[tr] 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,源碼如下:

Java代碼
  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[tr] childs = new ArrayList[tr]();  
  23.         }  
  24.   
  25.         private List superTreeNodes = new ArrayList();  
  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 GetTreeNode() {  
  35.                 return superTreeNodes;  
  36.         }  
  37.   
  38.         public void UpdateTreeNode(List 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[tr] 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.   
  129.         public int getGroupCount() {  
  130.                 return superTreeNodes.size();  
  131.         }  
  132.   
  133.         public long getGroupId(int groupPosition) {  
  134.                 return groupPosition;  
  135.         }  
  136.   
  137.         public boolean isChildSelectable(int groupPosition, int childPosition) {  
  138.                 return true;  
  139.         }  
  140.   
  141.         public boolean hasStableIds() {  
  142.                 return true;  
  143.         }  
  144. }  

       總結,使用ExpandableList實現三級樹形菜單時有些bug不好解決,而且定義三維數組的時候也要倍加小心......所以盡量把數據化簡來使用二級樹形菜單。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved