在網上搜了很長時間,沒有找到合适的Android三級菜單,是以就自己動手寫了一個,主要使用了BaseExpandableList來實作,通過三個布局檔案來完成對應的菜單項,具體實作請參照下圖。

通過上面兩圖可以看出為三級菜單,每一個菜單對應一個實體類,可以通過json解析資料加載進來,這裡就不過多解釋了,直接上源碼!
Activity實作類:
package com.zkq.activity;
import java.util.ArrayList;
import java.util.List;
import com.example.teltest.R;
import com.zkq.model.FirstItem;
import com.zkq.model.SecondItem;
import com.zkq.model.ThirdItem;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;
import com.zkq.adapter.*;
public class MainActivity extends Activity {
private ExpandableListView listView;
private List<FirstItem> firstList;
private ExpandableListAdapter eAdpater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView() {
// TODO Auto-generated method stub
listView = (ExpandableListView) findViewById(R.id.expandList);
firstList = new ArrayList<FirstItem>();
}
private void initData() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
FirstItem firstItem = new FirstItem();
firstItem.setId(i);
firstItem.setTitle("這是第" + i + "個");
List<SecondItem> seList = new ArrayList<SecondItem>();
for (int j = i; j < 10; j++) {
SecondItem secondItem = new SecondItem();
secondItem.setId(i);
secondItem.setTitle("子的第" + j * 78 + "條");
seList.add(secondItem);
List<ThirdItem> thirdList = new ArrayList<ThirdItem>();
for (int k = 0; k < j + 1; k++) {
ThirdItem thirdItem = new ThirdItem();
thirdItem.setId(k);
thirdItem.setImage("sss");
thirdItem.setName("張凱強" + k + j);
thirdItem.setTel("10086" + j + k);
thirdList.add(thirdItem);
}
secondItem.setThirdItems(thirdList);
}
firstItem.setSecondItems(seList);
firstList.add(firstItem);
}
eAdpater = new ExpandAdapter(MainActivity.this, firstList,stvClickEvent);
listView.setAdapter(eAdpater);
listView.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View view,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this,
childPosition + "---ccc===" + groupPosition,
Toast.LENGTH_LONG).show();
return false;
}
});
}
OnChildClickListener stvClickEvent = new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
String msg = "parent_id = " + groupPosition + " child_id = "
+ childPosition;
Toast.makeText(MainActivity.this, msg,
Toast.LENGTH_SHORT).show();
return false;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
兩個Adapter:
package com.zkq.adapter;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;
import com.example.teltest.R;
import com.zkq.model.FirstItem;
import com.zkq.model.SecondItem;
import com.zkq.util.Constants;
public class ExpandAdapter extends BaseExpandableListAdapter {
private Context context;
private List<FirstItem> firstList;
private OnChildClickListener stvClickEvent;//外部回調函數
// private List<SecondItem> secondList;
public ExpandAdapter(Context context, List<FirstItem> firstList,OnChildClickListener stvClickEvent) {
// TODO Auto-generated constructor stub
this.context = context;
this.firstList = firstList;
this.stvClickEvent=stvClickEvent;
// this.secondList = secondList;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return firstList.get(groupPosition).getSecondItems();
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ExpandableListView treeView = getExpandableListView(firstList.get(groupPosition).getSecondItems().size());
ExpandAdapter2 expandAdapter2 = new ExpandAdapter2(context, firstList,
childPosition, groupPosition,treeView,stvClickEvent);
//treeView.setOnChildClickListener(stvClickEvent);
treeView.setAdapter(expandAdapter2);
return treeView;
}
public ExpandableListView getExpandableListView(int position) {
AbsListView.LayoutParams params = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, Constants.SECOND_ITEM_HEIGHT*position);
ExpandableListView superTreeView = new ExpandableListView(context);
superTreeView.setLayoutParams(params);
return superTreeView;
}
@Override
public int getChildrenCount(int position) {
// TODO Auto-generated method stub
return 1;
}
@Override
public Object getGroup(int position) {
// TODO Auto-generated method stub
return firstList.get(position);
}
@Override
public int getGroupCount() {
// TODO Auto-generated method stub
return firstList.size();
}
@Override
public long getGroupId(int groupPosition) {
// TODO Auto-generated method stub
return groupPosition;
}
@Override
public View getGroupView(int position, boolean flag, View convertView,
ViewGroup group) {
// TODO Auto-generated method stub
FirstHolder holder = null;
if (convertView == null) {
holder = new FirstHolder();
convertView = LayoutInflater.from(context).inflate(
R.layout.first_lay, null);
holder.first_arrow = (ImageView) convertView
.findViewById(R.id.first_arrow);
holder.first_image = (ImageView) convertView
.findViewById(R.id.first_image);
holder.first_title = (TextView) convertView
.findViewById(R.id.first_title);
convertView.setTag(holder);
} else {
holder = (FirstHolder) convertView.getTag();
}
FirstItem firstItem = firstList.get(position);
holder.first_title.setText(firstItem.getTitle());
return convertView;
}
@Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isChildSelectable(int arg0, int arg1) {
// TODO Auto-generated method stub
return true;
}
}
class FirstHolder {
TextView first_title;
ImageView first_image;
ImageView first_arrow;
}
class SecondHolder {
TextView second_title;
ImageView second_arrow;
}
package com.zkq.adapter;
import java.util.List;
import com.example.teltest.R;
import com.zkq.activity.MainActivity;
import com.zkq.model.FirstItem;
import com.zkq.model.SecondItem;
import com.zkq.model.ThirdItem;
import com.zkq.util.Constants;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.AbsListView;
import android.widget.Toast;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.ImageView;
import android.widget.TextView;
public class ExpandAdapter2 extends BaseExpandableListAdapter {
private Context context;
private List<FirstItem> firstList;
private int cpostion;
private int gposition;
private ExpandableListView treeView;
private OnChildClickListener stvClickEvent;//外部回調函數
private int secondlength;
// private List<SecondItem> secondList;
public ExpandAdapter2(Context context, List<FirstItem> firstList,
int cposition, int gposition, ExpandableListView treeView,OnChildClickListener stvClickEvent) {
// TODO Auto-generated constructor stub
this.context = context;
this.firstList = firstList;
this.cpostion = cposition;
this.gposition = gposition;
this.treeView = treeView;
this.stvClickEvent=stvClickEvent;
// this.secondList = secondList;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return firstList.get(gposition).getSecondItems().get(groupPosition)
.getThirdItems().get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ThirdViewHolder childViewHolder = null;
if (convertView == null) {
childViewHolder = new ThirdViewHolder();
convertView = LayoutInflater.from(context).inflate(
R.layout.third_lay, null);
childViewHolder.third_name = (TextView) convertView
.findViewById(R.id.third_name);
childViewHolder.third_image = (ImageView) convertView
.findViewById(R.id.third_image);
childViewHolder.third_tel = (TextView) convertView
.findViewById(R.id.third_tel);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ThirdViewHolder) convertView.getTag();
}
ThirdItem thirdItem = firstList.get(gposition).getSecondItems()
.get(groupPosition).getThirdItems().get(childPosition);
childViewHolder.third_name.setText(thirdItem.getName());
childViewHolder.third_tel.setText(thirdItem.getTel());
//擷取選中的内容
treeView.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView arg0, View arg1, int groupPosition,
int childPosition, long arg4) {
// TODO Auto-generated method stub
String msg = "-ppp--"+gposition+"parent_id = " + groupPosition + " child_id = "
+ childPosition;
Toast.makeText(context, msg,
Toast.LENGTH_SHORT).show();
return false;
}
});
return convertView;
}
@Override
public int getChildrenCount(int position) {
// TODO Auto-generated method stub
return firstList.get(gposition).getSecondItems().get(position)
.getThirdItems().size();
}
@Override
public Object getGroup(int groupPosition) {
return firstList.get(gposition).getSecondItems().get(groupPosition);
}
@Override
public int getGroupCount() {
// TODO Auto-generated method stub
return firstList.get(gposition).getSecondItems().size();
}
@Override
public long getGroupId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getGroupView(int position, boolean arg1, View convertView,
ViewGroup arg3) {
SecondHolder childViewHolder = null;
if (convertView == null) {
childViewHolder = new SecondHolder();
convertView = LayoutInflater.from(context).inflate(
R.layout.second_lay, null);
childViewHolder.second_title = (TextView) convertView
.findViewById(R.id.second_title);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (SecondHolder) convertView.getTag();
}
SecondItem secondItem = firstList.get(gposition).getSecondItems()
.get(position);
childViewHolder.second_title.setText(secondItem.getTitle());
/***
* 展開監聽
*/
treeView.setOnGroupExpandListener(new OnGroupExpandListener() {
@Override
public void onGroupExpand(int position) {
// TODO Auto-generated method stub
if (treeView.getChildCount() == firstList.get(gposition)
.getSecondItems().size()) {
if (secondlength > 0) {
secondlength += firstList.get(gposition)
.getSecondItems().get(position).getThirdItems()
.size()
* Constants.THIRD_ITEM_HEIGHT;
} else {
secondlength += firstList.get(gposition)
.getSecondItems().size()
* Constants.SECOND_ITEM_HEIGHT
+ firstList.get(gposition).getSecondItems()
.get(position).getThirdItems().size()
* Constants.THIRD_ITEM_HEIGHT;
}
} else {
secondlength += firstList.get(gposition).getSecondItems()
.get(position).getThirdItems().size()
* Constants.THIRD_ITEM_HEIGHT;
}
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, secondlength);
treeView.setLayoutParams(lp);
}
});
// treeView.setOnGroupClickListener(new OnGroupClickListener() {
// @Override
// public boolean onGroupClick(ExpandableListView arg0, View arg1,
// int position, long arg3) {
// // TODO Auto-generated method stub
// return false;
// }
// });
/***
* 縮放監聽
*/
treeView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int position) {
// TODO Auto-generated method stub
secondlength -= firstList.get(gposition).getSecondItems()
.get(position).getThirdItems().size()
* Constants.THIRD_ITEM_HEIGHT;
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, secondlength);
treeView.setLayoutParams(lp);
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isChildSelectable(int arg0, int arg1) {
// TODO Auto-generated method stub
return true;
}
class ThirdViewHolder {
ImageView third_image;
TextView third_name;
TextView third_tel;
}
class SecondViewHolder {
TextView second_title;
ImageView second_arrow;
}
}
下面時三個實體類:
package com.zkq.model;
import java.util.List;
public class FirstItem {
private int id;
private String title;
private String image;
private List<SecondItem> secondItems;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public List<SecondItem> getSecondItems() {
return secondItems;
}
public void setSecondItems(List<SecondItem> secondItems) {
this.secondItems = secondItems;
}
}
package com.zkq.model;
import java.util.List;
public class SecondItem {
private int id;
private String title;
private List<ThirdItem> thirdItems;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<ThirdItem> getThirdItems() {
return thirdItems;
}
public void setThirdItems(List<ThirdItem> thirdItems) {
this.thirdItems = thirdItems;
}
}
package com.zkq.model;
public class ThirdItem {
private int id;
private String name;
private String tel;
private String image;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
常量
package com.zkq.util;
public class Constants {
/**
* 第二級和第三級菜單的高度
*/
public static final int SECOND_ITEM_HEIGHT=115;
public static final int THIRD_ITEM_HEIGHT=120;
}