在开发Android的时候,需要做一个多级的树状菜单,而且级数可能会变化,查阅网上很多材料,受到很大启发,之前网上找过一个,当时完成了功能要求,但存在几个问题,今天重新拿出原来长长的代码,经过增删及自己的理解,终于整理出来啦。
源码资源下载http://download.csdn.net/detail/op_kapu/5815691
大体的思路:点开父亲节点的时候,把子节点添加到listview中,刷新listview
关闭父亲节点的时候,把子节点从listview中删除,刷新listview
先上图:
然后是代码~
TreeNode.java
package com.example.treetest;
import java.util.ArrayList;
import java.util.List;
/**
* 树节点对象
*
* @author Kapu
*/
public class TreeNode {
private String title;
private boolean hasChildren;
private int Level;
private List<TreeNode> children = new ArrayList<TreeNode>();
private boolean expanded;
public void addChild(TreeNode node) {
this.hasChildren = true;
this.children.add(node);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getLevel() {
return Level;
}
public void setLevel(int level) {
Level = level;
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
public boolean hasChildren() {
return hasChildren;
}
public void hasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
public List<TreeNode> getChildren() {
return children;
}
public void setChildren(List<TreeNode> children) {
this.hasChildren = true;
this.children = children;
}
}
TreeViewAdapter.java
package com.example.treetest;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class TreeViewAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private List<TreeNode> mfilelist;
private Bitmap mIconCollapse; //- , 收缩
private Bitmap mIconExpand; //+ ,展开
public TreeViewAdapter(Context context, List<TreeNode> treeNodes) {
super();
mInflater = LayoutInflater.from(context);
mfilelist = treeNodes;
mIconCollapse = BitmapFactory.decodeResource(context.getResources(), R.drawable.plus);
mIconExpand = BitmapFactory.decodeResource(context.getResources(), R.drawable.minus);
}
public int getCount() {
return mfilelist.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
convertView = mInflater.inflate(R.layout.tree_node, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.treetext);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
final TreeNode obj = mfilelist.get(position);
int level = obj.getLevel();
holder.icon.setPadding( 15 * (level + 1),
holder.icon.getPaddingTop(), 0,
holder.icon.getPaddingBottom());
holder.text.setText(obj.getTitle());
if (obj.hasChildren()&& (obj.isExpanded() == false)) {
holder.icon.setImageBitmap(mIconCollapse);
} else if (obj.hasChildren() && (obj.isExpanded() == true)) {
holder.icon.setImageBitmap(mIconExpand);
} else if (!obj.hasChildren()) {
holder.icon.setImageBitmap(mIconCollapse);
holder.icon.setVisibility(View.INVISIBLE);
}
return convertView;
}
class ViewHolder {
TextView text;
ImageView icon;
}
}
MainActivity.java
package com.example.treetest;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import android.app.Activity;
public class MainActivity extends Activity{
/** 左侧树 */
private List<TreeNode> nodes = new ArrayList<TreeNode>();
private TreeViewAdapter treeViewAdapter = null;
/** 目录树数据 */
private ListView dir;
/** 当前在左侧目录选中的位置 */
int currentPosition;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dir = (ListView) findViewById(R.id.dir);
//初始化数据
List<TreeNode> treeNodeList = new ArrayList<TreeNode>();
TreeNode tree0 = new TreeNode();
tree0.setLevel(0);
tree0.setTitle("第一章");
List<TreeNode> treeNodeList0 = new ArrayList<TreeNode>();
TreeNode tree00 = new TreeNode();
tree00.setLevel(1);
tree00.setTitle("第一课");
TreeNode tree01 = new TreeNode();
tree01.setLevel(1);
tree01.setTitle("第二课");
List<TreeNode> treeNodeList00 = new ArrayList<TreeNode>();
TreeNode tree000 = new TreeNode();
tree000.setLevel(2);
tree000.setTitle("第二课第一节");
TreeNode tree001 = new TreeNode();
tree001.setLevel(2);
tree001.setTitle("第二课第二节");
treeNodeList00.add(tree000);
treeNodeList00.add(tree001);
tree01.setChildren(treeNodeList00);
treeNodeList0.add(tree00);
treeNodeList0.add(tree01);
tree0.setChildren(treeNodeList0);
tree0.hasChildren(true);
TreeNode tree1 = new TreeNode();
tree1.setLevel(0);
tree1.setTitle("第二章");
treeNodeList.add(tree0);
treeNodeList.add(tree1);
nodes = treeNodeList;
dir.setDivider(null);
treeViewAdapter = new TreeViewAdapter(this, nodes);
dir.setAdapter(treeViewAdapter);
dir.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> l, View v, int position,
long id) {
// 此节点下没有子节点,即某一个小节
if (!nodes.get(position).hasChildren()) {
return;
}
// 假如 此父节点下有子节点,且 已展开 关闭的时候删除
if (nodes.get(position).isExpanded()) {
nodes.get(position).setExpanded(false);
TreeNode element = nodes.get(position); // 先得到该 父节点
ArrayList<TreeNode> temp = new ArrayList<TreeNode>();
// 循环得到 子节点
for (int i = position + 1; i < nodes.size(); i++) {
if (element.getLevel() >= nodes.get(i).getLevel()) {
break;
}
temp.add(nodes.get(i));
}
nodes.removeAll(temp);
treeViewAdapter.notifyDataSetChanged();
} else {
// 假如 此父节点未展开,则 展开 展开的时候增加
TreeNode obj = nodes.get(position);
obj.setExpanded(true);
int level = obj.getLevel(); // 父节点级数
int nextLevel = level + 1; // 子节点 级数 = 父节点级数+1
int temp = position;//临时位置
// 循环 得到 此父节点的所有子节点
for (TreeNode element : obj.getChildren()) {
element.setLevel(nextLevel);
element.setExpanded(false);
temp = temp+1;
nodes.add(temp, element);
}
// 将已变化的nodes列表 刷新
treeViewAdapter.notifyDataSetChanged();
}
}
});
}
}