-
private int icon;
-
/**
-
* 下一级的子Node
-
*/
-
private List children = new ArrayList();
-
/**
-
* 父Node
-
*/
-
private Node parent;
-
public Node()
-
{
-
}
-
public Node(int id, int pId, String name)
-
{
-
super();
-
this.id = id;
-
this.pId = pId;
-
this.name = name;
-
}
-
public int getIcon()
-
{
-
return icon;
-
}
-
public void setIcon(int icon)
-
{
-
this.icon = icon;
-
}
-
public int getId()
-
{
-
return id;
-
}
-
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;
-
}
-
public void setLevel(int level)
-
{
-
this.level = level;
-
}
-
public boolean isExpand()
-
{
-
return isExpand;
-
}
-
public List getChildren()
-
{
-
return children;
-
}
-
public void setChildren(List children)
-
{
-
this.children = children;
-
}
-
public Node getParent()
-
{
-
return parent;
-
}
-
public void setParent(Node parent)
-
{
-
this.parent = parent;
-
}
-
/**
-
* 是否为跟节点
-
*
-
* @return
-
*/
-
public boolean isRoot()
-
{
-
return parent == null;
-
}
-
/**
-
* 判断父节点是否展开
-
*
-
* @return
-
*/
-
public boolean isParentExpand()
-
{
-
if (parent == null)
-
return false;
-
return parent.isExpand();
-
}
-
/**
-
* 是否是叶子界点
-
*
-
* @return
-
*/
-
public boolean isLeaf()
-
{
-
return children.size() == 0;
-
}
-
/**
-
* 获取level
-
*/
-
public int getLevel()
-
{
-
return parent == null ? 0 : parent.getLevel() + 1;
-
}
-
/**
-
* 设置展开
-
*
-
* @param isExpand
-
*/
-
public void setExpand(boolean isExpand)
-
{
-
this.isExpand = isExpand;
-
if (!isExpand)
-
{
-
for (Node node : children)
-
{
-
node.setExpand(isExpand);
-
}
-
}
-
}
-
}
包含了树节点一些常见的属性,一些常见的方法;对于getLevel,setExpand这些方法,大家可以好好看看~
有了Node,刚才的用法中,出现的就是我们Adapter所继承的超类:TreeListViewAdapter;核心代码都在里面,我们准备去一探究竟:
代码不是很长,直接完整的贴出:
[java] view plain copy
-
package com.zhy.tree.bean;
-
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;
-
public abstract class TreeListViewAdapter extends BaseAdapter
-
{
-
protected Context mContext;
-
/**
-
* 存储所有可见的Node
-
*/
-
protected List mNodes;
-
protected LayoutInflater mInflater;
-
/**
-
* 存储所有的Node
-
*/
-
protected List mAllNodes;
-
/**
-
* 点击的回调接口
-
*/
-
private OnTreeNodeClickListener onTreeNodeClickListener;
-
public interface OnTreeNodeClickListener
-
{
-
void onClick(Node node, int position);
-
}
-
public void setOnTreeNodeClickListener(
-
OnTreeNodeClickListener onTreeNodeClickListener)
-
{
-
this.onTreeNodeClickListener = onTreeNodeClickListener;
-
}
-
/**
-
*
-
* @param mTree
-
* @param context
-
* @param datas
-
* @param defaultExpandLevel
-
* 默认展开几级树
-
* @throws IllegalArgumentException
-
* @throws IllegalAccessException
-
*/
-
public TreeListViewAdapter(ListView mTree, Context context, List datas,
-
int defaultExpandLevel) throws IllegalArgumentException,
-
IllegalAccessException
-
{
-
mContext = context;
-
/**
-
* 对所有的Node进行排序
-
*/
-
mAllNodes = TreeHelper.getSortedNodes(datas, defaultExpandLevel);
-
/**
-
* 过滤出可见的Node
-
*/
-
mNodes = TreeHelper.filterVisibleNode(mAllNodes);
-
mInflater = LayoutInflater.from(context);
-
/**
-
* 设置节点点击时,可以展开以及关闭;并且将ItemClick事件继续往外公布
-
*/
-
mTree.setOnItemClickListener(new OnItemClickListener()
-
{
-
@Override
-
public void onItemClick(AdapterView<?> parent, View view,
-
int position, long id)
-
{
-
expandOrCollapse(position);
-
if (onTreeNodeClickListener != null)
-
{
-
onTreeNodeClickListener.onClick(mNodes.get(position),
-
position);
-
}
-
}
-
});
-
}
-
/**
-
* 相应ListView的点击事件 展开或关闭某节点
-
*
-
* @param position
-
*/
-
public void expandOrCollapse(int position)
-
{
-
Node n = mNodes.get(position);
-
if (n != null)// 排除传入参数错误异常
-
{
-
if (!n.isLeaf())
-
{
-
n.setExpand(!n.isExpand());
-
mNodes = TreeHelper.filterVisibleNode(mAllNodes);
-
notifyDataSetChanged();// 刷新视图
-
}
-
}
-
}
-
@Override
-
public int getCount()
-
{
-
return mNodes.size();
-
}
-
@Override
-
public Object getItem(int position)
-
{
-
return mNodes.get(position);
-
}
-
@Override
-
public long getItemId(int position)
-
{
-
return position;
-
}
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent)
-
{
-
Node node = mNodes.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);
-
}
首先我们的类继承自BaseAdapter,然后我们对应的数据集是,过滤出的可见的Node;
我们的构造方法默认接收4个参数:listview,context,mdatas,以及默认展开的级数:0只显示根节点;
可以在构造方法中看到:对用户传入的数据集做了排序,和过滤的操作;一会再看这些方法,这些方法我们使用了一个TreeHelper进行了封装。
注:如果你觉得你的Item布局十分复杂,且布局会展示Bean的其他数据,那么为了方便,你可以让Node中包含一个泛型T , 每个Node携带与之对于的Bean的所有数据;
可以看到我们还直接为Item设置了点击事件,因为我们树,默认就有点击父节点展开与关闭;但是为了让用户依然可用点击监听,我们自定义了一个点击的回调供用户使用;
当用户点击时,默认调用expandOrCollapse方法,将当然节点重置展开标志,然后重新过滤出可见的Node,最后notifyDataSetChanged即可;
其他的方法都是BaseAdapter默认的一些方法了。
下面我们看下TreeHelper中的一些方法:
首先看TreeListViewAdapter构造方法中用到的两个方法:
[java] view plain copy
-
/**
-
* 传入我们的普通bean,转化为我们排序后的Node
-
* @param datas
-
* @param defaultExpandLevel
-
* @return
-
* @throws IllegalArgumentException
-
* @throws IllegalAccessException
-
*/
-
public static List getSortedNodes(List datas,
-
int defaultExpandLevel) throws IllegalArgumentException,
-
IllegalAccessException
-
{
-
List result = new ArrayList();
-
//将用户数据转化为List以及设置Node间关系
-
List nodes = convetData2Node(datas);
-
//拿到根节点
-
List rootNodes = getRootNodes(nodes);
-
//排序
-
for (Node node : rootNodes)
-
{
-
addNode(result, node, defaultExpandLevel, 1);
-
}
-
return result;
-
}
拿到用户传入的数据,转化为List以及设置Node间关系,然后根节点,从根往下遍历进行排序;
接下来看:filterVisibleNode
[java] view plain copy
-
/**
-
* 过滤出所有可见的Node
-
*
-
* @param nodes
-
* @return
-
*/
-
public static List filterVisibleNode(List nodes)
-
{
-
List result = new ArrayList();
-
for (Node node : nodes)
-
{
-
// 如果为跟节点,或者上层目录为展开状态
-
if (node.isRoot() || node.isParentExpand())
-
{
-
setNodeIcon(node);
-
result.add(node);
-
}
-
}
-
return result;
-
}
过滤Node的代码很简单,遍历所有的Node,只要是根节点或者父节点是展开状态就添加返回;
最后看看这两个方法用到的别的一些私有方法:
[java] view plain copy
-
/**
-
* 将我们的数据转化为树的节点
-
*
-
* @param datas
-
* @return
-
* @throws NoSuchFieldException
-
* @throws IllegalAccessException
-
* @throws IllegalArgumentException
-
*/
-
private static List convetData2Node(List datas)
-
throws IllegalArgumentException, IllegalAccessException
-
{
-
List nodes = new ArrayList();
-
Node node = null;
-
for (T t : datas)
-
{
-
int id = -1;
-
int pId = -1;
-
String label = null;
-
Class<? extends Object> clazz = t.getClass();
-
Field[] declaredFields = clazz.getDeclaredFields();
-
for (Field f : declaredFields)
-
{
-
if (f.getAnnotation(TreeNodeId.class) != null)
-
{
-
f.setAccessible(true);
-
id = f.getInt(t);
-
}
-
if (f.getAnnotation(TreeNodePid.class) != null)
-
{
-
f.setAccessible(true);
-
pId = f.getInt(t);
-
}
-
if (f.getAnnotation(TreeNodeLabel.class) != null)
-
{
-
f.setAccessible(true);
-
label = (String) f.get(t);
-
}
-
if (id != -1 && pId != -1 && label != null)
-
{
-
break;
-
}
-
}
-
node = new Node(id, pId, label);
-
nodes.add(node);
-
}
-
/**
-
* 设置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)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后我还整理了很多Android中高级的PDF技术文档。以及一些大厂面试真题解析文档。需要的朋友都可以点击GitHub直接获取方式
Android高级架构师之路很漫长,一起共勉吧!
{
-
m.getChildren().add(n);
-
n.setParent(m);
-
}
-
}
-
}
-
// 设置图片
-
for (Node n : nodes)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-SHBgkaIE-1711043890923)]
[外链图片转存中…(img-guNNfH9b-1711043890924)]
[外链图片转存中…(img-gYYUWQx4-1711043890924)]
[外链图片转存中…(img-Jd9b3NFG-1711043890925)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-4gzeH7vF-1711043890926)]
最后我还整理了很多Android中高级的PDF技术文档。以及一些大厂面试真题解析文档。需要的朋友都可以点击GitHub直接获取方式
[外链图片转存中…(img-vXtxK05C-1711043890927)]
Android高级架构师之路很漫长,一起共勉吧!