首先来一张萌萌哒的效果图(比较懒 - -)

然后是代码:

//  Node
package com.example.treeview.utils; import java.util.ArrayList;
import java.util.List; public class Node { public Node() {
super();
} public Node(int id, int pId, String name) {
super();
this.id = id;
this.pId = pId;
this.name = name;
} private int id;
/**
* 根节点的层级
*/
private int pId = 0;
private String name;
/**
* 树的层级
*/
private int level;
/**
* 是否展开
*/
private boolean isExpand = false;
private int icon; private Node parent;
private List<Node> children = new ArrayList<Node>(); /**
* 判断是否为根节点
*
* @return
*/
public boolean isRoot() {
return parent == null;
} public int getId() {
return id;
} /**
* 判断当前父节点是否展开
*
* @return
*/
public boolean isparentExpand() {
if (parent == null) {
return false;
} else {
return parent.isExpand;
}
} /**
* 判断是否为叶节点
*
* @return
*/
public boolean isLeaf() {
return children.size() == 0;
} public void setId(int id) {
this.id = id;
} public int getpId() {
return pId;
} public void setpId(int pId) {
this.pId = pId;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} /**
* 得到当前节点的层级
*
* @return
*/
public int getLevel() {
return parent == null ? 0 : parent.getLevel() + 1;
} public void setLevel(int level) {
this.level = level;
} public boolean isExpand() {
return isExpand;
} public void setExpand(boolean isExpand) {
this.isExpand = isExpand;
if (isExpand) {
for (Node node : children) {
node.setExpand(false);
}
}
} public int getIcon() {
return icon;
} public void setIcon(int icon) {
this.icon = icon;
} public Node getParent() {
return parent;
} public void setParent(Node parent) {
this.parent = parent;
} public List<Node> getChildren() {
return children;
} public void setChildren(List<Node> children) {
this.children = children;
} }
//FileBean
package com.example.treeview.bean; import com.example.treeview.utils.annotation.TreeNodeId;
import com.example.treeview.utils.annotation.TreeNodeLable;
import com.example.treeview.utils.annotation.TreeNodePid; public class FileBean { @TreeNodeId
private int id;
@TreeNodePid
private int pId;
@TreeNodeLable
private String label; public FileBean(int id, int pId, String label) {
super();
this.id = id;
this.pId = pId;
this.label = label;
} private String desc;
}
// 注解
package com.example.treeview.utils.annotation; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME.RUNTIME)
public @interface TreeNodeId { } package com.example.treeview.utils.annotation; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME.RUNTIME)
public @interface TreeNodeLable { } package com.example.treeview.utils.annotation; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME.RUNTIME)
public @interface TreeNodePid { }
//TreeHelper
package com.example.treeview.utils; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List; import com.example.treeview.utils.annotation.TreeNodeId;
import com.example.treeview.utils.annotation.TreeNodeLable;
import com.example.treeview.utils.annotation.TreeNodePid; public class TreeHelper { /**
* 将用户的数据转化为树形数据
*
* @param datas
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static <T> List<Node> convertDatasNodes(List<T> datas)
throws IllegalAccessException, IllegalArgumentException {
List<Node> nodes = new ArrayList<Node>();
Node node = null;
for (T t : datas) { int id = -1;
int pId = -1;
String lable = null;
node = new Node();
Class clazz = t.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotation(TreeNodeId.class) != null) {
field.setAccessible(true);
id = field.getInt(t);
}
if (field.getAnnotation(TreeNodePid.class) != null) {
field.setAccessible(true);
pId = field.getInt(t);
}
if (field.getAnnotation(TreeNodeLable.class) != null) {
field.setAccessible(true);
lable = (String) field.get(t);
}
}
node = new Node(id, pId, lable);
nodes.add(node);
}
/**
*
* 设置节点间的关系
*/
for (int i = 0; i < nodes.size(); i++) {
Node n=nodes.get(i);
for (int j =i+1; j <nodes.size(); j++) {
Node m=nodes.get(j);
if (m.getpId()==n.getId()) {
n.getChildren().add(m);
m.setParent(n);
}else if (m.getId()==n.getpId()) {
m.getChildren().add(n);
n.setParent(m);
}
}
} for (Node n:nodes) {
setNodeIcon(n);
}
return nodes;
} /**
* 设置过滤出可见的节点
* @param nodes
* @return
*/
public static List<Node> filterVisibleNodeS(List<Node> nodes){
List<Node> reuslt=new ArrayList<Node>();
for (Node node : nodes) {
if (node.isRoot()||node.isparentExpand()) {
setNodeIcon(node);
reuslt.add(node);
}
}
return reuslt;
} /**
*
* @param datas
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static <T> List<Node> getSortedNodes(List<T> datas,int defaultExpandLevel) throws IllegalAccessException, IllegalArgumentException{
List<Node> result=new ArrayList<Node>();
List<Node> nodes=convertDatasNodes(datas);
List<Node> rootNodes=getRootNodes(nodes);
for (Node node : rootNodes) {
AddNode(result,node,defaultExpandLevel,1);
}
return result;
} /**
* 把一个节点的所有孩子节点都放入result
* @param result
* @param node
* @param defaultExpandLevel
* @param currentLevel
*/
private static void AddNode(List<Node> result, Node node,
int defaultExpandLevel, int currentLevel) {
result.add(node);
if (defaultExpandLevel>=currentLevel) {
node.setExpand(true);
}
if (node.isLeaf()) {
return;
}
for (int i = 0; i < node.getChildren().size(); i++) {
AddNode(result, node.getChildren().get(i), defaultExpandLevel, currentLevel+1);
}
} /**
* 从所有节点中过滤出根节点
* @param nodes
* @return
*/
private static List<Node> getRootNodes(List<Node> nodes) {
List<Node> root=new ArrayList<Node>();
for (Node node : nodes) {
if (node.isRoot()) {
root.add(node);
}
}
return root;
} /**
* 为Node设置图标
* @param n
*/
private static void setNodeIcon(Node n) {
if (n.getChildren().size()>0&&n.isExpand()) {
n.setIcon(0);
}else if(n.getChildren().size()>0&&!n.isExpand()){
n.setIcon(1);
}else {
n.setIcon(-1);
}
}
}
//TreeListViewAdapter
package com.example.treeview.adapter; import java.util.List; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView; import com.example.treeview.utils.Node;
import com.example.treeview.utils.TreeHelper; public abstract class TreeListViewAdapter<T> extends BaseAdapter { protected Context mContext;
protected List<Node> mAllNodes;
protected List<Node> mVisibleNodes;
protected LayoutInflater mInflater;
protected ListView mTree; /**
* 设置Node的点击回调
*
* @author az
*
*/
private interface OnTreeNodeClickListener {
void onClick(Node node, int position);
} private OnTreeNodeClickListener mListener; public void setOnTreeNodeClickListener(OnTreeNodeClickListener mListener) {
this.mListener = mListener;
} public OnTreeNodeClickListener getmListener() {
return mListener;
} public void setmListener(OnTreeNodeClickListener mListener) {
this.mListener = mListener;
} public TreeListViewAdapter(ListView mTree, Context context, List<T> datas,
int defaultExpandLevel) throws IllegalAccessException,
IllegalArgumentException {
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.mAllNodes = TreeHelper.getSortedNodes(datas, defaultExpandLevel);
this.mVisibleNodes = TreeHelper.filterVisibleNodeS(mAllNodes);
this.mTree = mTree;
this.mTree.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
expandOrCollapse(position);
if (mListener != null) {
mListener.onClick(mVisibleNodes.get(position), position);
}
}
});
} /**
* 点击收缩或者展开
*
* @param position
*/
private void expandOrCollapse(int position) {
Node n = mVisibleNodes.get(position);
if (n != null) {
if (n.isLeaf())
return;
n.setExpand(!n.isExpand());
mVisibleNodes = TreeHelper.filterVisibleNodeS(mAllNodes);
notifyDataSetChanged();
}
} @Override
public int getCount() {
return mVisibleNodes.size();
} @Override
public Object getItem(int position) {
return mVisibleNodes.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
Node node=mVisibleNodes.get(position);
convertView=getConvertView(node, position, convertView, parent);
convertView.setPadding(node.getLevel()*30, 3, 3,3);
return convertView;
} public abstract View getConvertView(Node node,int position,View convertView,ViewGroup parent); }
//SimpleTreeListViewAdapter   继承TreeLivewAdapter方便使用
package com.example.treeview.adapter; import java.util.List; import com.example.threeview.R;
import com.example.treeview.utils.Node; import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; public class SimpleTreeListViewAdapter<T> extends TreeListViewAdapter<T> { public SimpleTreeListViewAdapter(ListView mTree, Context context,
List<T> datas, int defaultExpandLevel)
throws IllegalAccessException, IllegalArgumentException {
super(mTree, context, datas, defaultExpandLevel);
// TODO Auto-generated constructor stub
} @Override
public View getConvertView(Node node, int position, View convertView,
ViewGroup parent) {
ViewHolder holder=null;
if (convertView==null) {
convertView=mInflater.inflate(R.layout.list_item, parent,false);
holder=new ViewHolder();
holder.mIcon=(ImageView) convertView.findViewById(R.id.iv_itemicon);
holder.mText=(TextView) convertView.findViewById(R.id.tv_itemtext);
convertView.setTag(holder);
}else {
holder=(ViewHolder) convertView.getTag();
}
holder.mText.setText(node.getName());
return convertView;
} private class ViewHolder{
ImageView mIcon;
TextView mText;
} }
//MainActivity

package com.example.treeview;

import java.util.ArrayList;
import java.util.List; import com.example.threeview.R;
import com.example.treeview.adapter.SimpleTreeListViewAdapter;
import com.example.treeview.bean.FileBean; import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView; public class MainActivity extends Activity { private ListView mTree;
private SimpleTreeListViewAdapter<FileBean> mAdapter;
private List<FileBean> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTree=(ListView) findViewById(R.id.lv);
initDatas();
try {
mAdapter=new SimpleTreeListViewAdapter<>(mTree, this, mDatas, 0);
mTree.setAdapter(mAdapter);
} catch (IllegalAccessException | IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
private void initDatas() {
mDatas=new ArrayList<FileBean>();
FileBean bean=new FileBean(1, 0, "根1");
mDatas.add(bean);
bean=new FileBean(2, 0, "根2");
mDatas.add(bean);
bean=new FileBean(3, 1, "根1-1");
mDatas.add(bean);
bean=new FileBean(4, 2, "根2-1");
mDatas.add(bean);
} }

在上面的adapter里面有自定义的一个,使用方法:

mAdapter.setOnTreeNodeClickListener(new );

提供了一个OnClick方法:

onClick(Node node, int position)

参考:http://www.imooc.com/learn/303

Android 树形菜单的更多相关文章

  1. Android学习笔记之树形菜单的应用...

    PS:终于考完试了,总算是解脱了...可以正式上手项目开发了.... 学习内容: 1.掌握如何使用树形菜单...   对知识点进行一下补充...居然忘记了去学习树形菜单...不过在这里补上... Ex ...

  2. Android 多级树形菜单

    在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单... ...

  3. jQuery 树形菜单

    树形菜单 在 jQuery easyu中其左侧的主菜单使用的是 easyui 中的 tree 组件,不是太熟悉,不过感觉不是太好用. 比如 easyui 中的 tree 需要单击分叉节点前的小三角,才 ...

  4. JS树形菜单

    超全的JS树形菜单源代码共享(有实例图) 树形菜单是很常用的效果,常用在管理软件当中,但是一套树形菜单已经不能满足需求,所以如果能有一套比较全面的树形菜单JS特效代码,将会非常方便,下面懒人萱将超全的 ...

  5. 简单实用的二级树形菜单hovertree

    原创 hovertree是一个仿京东的树形菜单jquery插件,暂时有银色和绿色两种. 官方网址:http://keleyi.com/jq/hovertree/欢迎下载使用 查看绿色效果:http:/ ...

  6. Vue.js 递归组件实现树形菜单

    最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: import Vue from 'vue' Vue.config.debug = tr ...

  7. EasyUI创建异步树形菜单和动态添加标签页tab

    创建异步树形菜单 创建树形菜单的ul标签 <ul class="easyui-tree" id="treeMenu"> </ul> 写j ...

  8. Android侧滑菜单代码实现

    前两天学习了hyman老师讲的Android侧滑菜单的实现,经过自己的整理分享出来给大家学习一下 现在很多APP都有菜单侧滑的功能,本篇文章主要讲解使用自定义的HorizontalScrollView ...

  9. WEB开发中前后台树形菜单的展示设计

    在WEB开发中经常需要进行树形菜单的展示,本例通过不同角度的总结了如下三种实现方式: 通过JS的递归实现前端菜单DOM的动态创建 通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示 ...

随机推荐

  1. DB2 runstats和reorg操作

    [db2inst1@xifenfei ~]$ db2 connect to xff      Database Connection Information    Database server    ...

  2. powerdesigner 转换各种数据库SQL

    转各种SQL脚本的步骤 一.

  3. Windows中的句柄

    (一)句柄 在程序设计中,句柄(handle)是一种特殊的智能指针.当一个应用程序要引用其他系统(如数据库.操作系统)所管理的内存块或对象时,就要使用句柄. 句柄与普通指针的区别在于,指针包含的是引用 ...

  4. C++学习之重载运算符1

    C++除可重载函数之后,还允许定义已有的运算符,这样通过运算符重载可像处理数据使用它们. 先来个代码 #include<iostream> using namespace std; cla ...

  5. hdu 5446 Unknown Treasure 中国剩余定理+lucas

    题目链接 求C(n, m)%p的值, n, m<=1e18, p = p1*p2*...pk. pi是质数. 先求出C(n, m)%pi的值, 然后这就是一个同余的式子. 用中国剩余定理求解. ...

  6. web2py官方文档翻译

    00前言 我相信能够轻松地构建高质量增长的web应用程序是至关重要的一个自由和开放的社会.这可以防止玩家最大的垄断信息的流通. 因此我从2007年开始web2py项目,主要是作为一种教学工具与简化we ...

  7. Linux--本地yum库

    Linux配置本地yum云: 第一步:把cd 挂载到目录树 mount /dev/cdrom /mnt/media 第二步:增加/etc/yum.repo.d/local.repo touch /et ...

  8. HttpContext.Current.Cache 过期时间

    原文:HttpContext.Current.Cache 过期时间 为了更快的读取数据,我们一般会把常用到的数据加载到Cache中 在.NET中,Cache的存在可以依赖多中方式,主要用到HttpCo ...

  9. 适合入门自学服装裁剪滴书(更新ing)

    [♣]适合入门自学服装裁剪滴书(更新ing) [♣]适合入门自学服装裁剪滴书(更新ing) 适合入门自学服装裁剪滴书(更新ing) 来自: 裁缝阿普(不为良匠,便为良医.) 2014-04-06 23 ...

  10. python-多线程(原理篇)

    多线程的基本概念 语言学习总是绕不过一些东西,例如多进程和多线程,最近越来越发现,上来看几个实例练习一下过几天就不知其所以然了.所以还是先看看原理,在看实例练习吧! 线程的概念 概念:线程是进程中执行 ...