600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > android树状结构导航图

android树状结构导航图

时间:2024-02-04 22:18:10

相关推荐

android树状结构导航图

本文参考Hongyang大神文章 /lmj623565791/article/details/40212367 ,自己写个demo记录下。

先看效果图:

总思路:

将每条数据都看作是listview的一个item,按照它们之间的关系,将这些item由上到下排序。然后将每个item设置为不同的显示状态,再加上点击每个item会联动其他相应item的显示状态改变,这样就达到了树状结构导航的目的。

1、将每条原始数据都转化为节点数据,因为每个节点数据里有:

a、子节点、父节点:这个很重要,因为每条数据的缩进、图标的设置、是否展示,都要依据每条数据间的父子关系来进行判断展示;

b、左边距的空格数:设置缩进,以展现树状结构效果

c、展开的状态:说明此节点目前是否展开

2、在适配器配置这条节点数据的View时,依据这条节点数据的各个属性,来做不同的展示,以达到最终树状结构展示效果的目的。

写完这个demo,让我深刻的认识到了一个道理:

每个控件其实都对应一条数据,“控件展示状态的改变”本质上其实就是“它所对应的那条数据中的某个参数改变了”而已。

原始数据Bean:

public class Bean {@TreeIdint id;@TreePidint pid;@TreeLabelString name;public Bean(int id, int pid, String name) {this.id = id;this.pid = pid;this.name = name;}}

节点数据Node:

public class Node {public Node(int id, int pid, String name) {this.id = id;this.pid = pid;this.name = name;}int id;int pid;String name;/*** 子节点*/List<Node> children = new ArrayList<>();/*** 父节点*/Node parent;/*** 前面有几个单位的空格*/int level;/*** 是否是展开状态*/boolean isExpand = false;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 List<Node> getChildren() {return children;}public Node getParent() {return parent;}public void setParent(Node parent) {this.parent = parent;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getLevel() {return level;}public void setLevel(int level) {this.level = level;}public void setExpand(boolean expand) {isExpand = expand;}}

Activity:

public class MainActivity extends Activity {/*** 原始数据*/List<Bean> beans = new ArrayList<>();/*** 由原始数据转化的节点数据*/List<Node> nodes = new ArrayList<>();/*** 经过排序的节点数据*/List<Node> sortedNodes = new ArrayList<>();/*** 适配器*/TreeListViewAdapter adapter;/*** listview*/ListView lv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lv = (ListView) findViewById(R.id.lv);//初始化原始数据beans.add(new Bean(10, 7, "东北人"));beans.add(new Bean(4, 1, "人"));beans.add(new Bean(12, 8, "广东人"));beans.add(new Bean(2, 1, "猴子"));beans.add(new Bean(5, 2, "金丝猴"));beans.add(new Bean(7, 4, "北方人"));beans.add(new Bean(3, 1, "龙"));beans.add(new Bean(1, 0, "动物"));beans.add(new Bean(9, 7, "内蒙人"));beans.add(new Bean(6, 2, "猕猴"));beans.add(new Bean(11, 7, "北京人"));beans.add(new Bean(8, 4, "南方人"));try {//将原始数据转化为节点数据nodes = TreeHelper.data2Node(beans);//将节点数据排序sortedNodes = TreeHelper.sort(nodes);//将排好顺序的节点数据传入适配器adapter = new TreeListViewAdapter(this, sortedNodes);//展示数据lv.setAdapter(adapter);} catch (IllegalAccessException e) {e.printStackTrace();}}}

TreeListViewAdapter:

public class TreeListViewAdapter extends BaseAdapter {List<Node> datas;Context context;public TreeListViewAdapter(Context context, List<Node> datas) {this.datas = datas;this.context = context;}@Overridepublic int getCount() {return datas.size();}@Overridepublic Object getItem(int i) {return null;}@Overridepublic long getItemId(int i) {return 0;}@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {final Node node = datas.get(i);ViewHolder viewHolder;if (view == null) {view = LayoutInflater.from(context).inflate(R.layout.item, null);viewHolder = new ViewHolder();viewHolder.tv = (TextView) view.findViewById(R.id.tv);viewHolder.iv = (ImageView) view.findViewById(R.id.iv);view.setTag(viewHolder);} else {viewHolder = (ViewHolder) view.getTag();}//显示文字viewHolder.tv.setText(node.getName());//点击节点时view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//如果节点当前状态是展开,那么将它的所有子孙节点都设置为关闭状态if(node.isExpand==true){TreeHelper.shutNode(node);}//将节点的展开状态改为相反node.setExpand(!node.isExpand);//刷新显示notifyDataSetChanged();}});//如果此节点有子节点if(node.children.size()>0){//节点状态是展开时,设置相应图标if(node.isExpand == true){viewHolder.iv.setImageResource(R.drawable.tree_ec);//节点状态是关闭时,设置相应图标}else {viewHolder.iv.setImageResource(R.drawable.tree_ex);}//如果此节点无子节点,设置图片为空}else {viewHolder.iv.setImageBitmap(null);}//设置此条item的左边距view.setPadding(node.getLevel()*50,0,0,0);//如果此节点为根节点或者它的父节点为展开状态,那么显示该节点;//否则,不显示此节点。Node parentNode = node.getParent();if (parentNode == null || parentNode.isExpand == true) {return view;} else{return null;}}class ViewHolder {ImageView iv;TextView tv;}}

TreeHelper:

public class TreeHelper {/*** 将原始数据转为节点数据* @param datas* @return* @throws IllegalAccessException*/public static List<Node> data2Node(List<Bean> datas) throws IllegalAccessException {List<Node> nodes = new ArrayList<>();Node node = null;//根据反射将数据源里的id、pid、name拿出来for (Bean t : datas) {int id = -1;int pid = -1;String label = null;Class<? extends Object> clazz = t.getClass();Field[] fields = clazz.getDeclaredFields();for (Field f : fields) {if (f.getAnnotation(TreeId.class) != null) {id = f.getInt(t);}if (f.getAnnotation(TreePid.class) != null) {pid = f.getInt(t);}if (f.getAnnotation(TreeLabel.class) != null) {label = (String) f.get(t);}if (id != -1 && pid != -1 && label != null) {break;}}node = new Node(id, pid, label);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 (n.getId() == m.getPid()) {n.getChildren().add(m);m.setParent(n);}if (n.getPid() == m.getId()) {n.setParent(m);m.getChildren().add(n);}}}//设置此节点左边距应该设置几个空格for (Node n : nodes) {n.setLevel(calPadding(n,0));}return nodes;}/*** 将节点数据按照父子级关系排序* @param nodes* @return*/public static List<Node> sort(List<Node> nodes) {//先将根节点选出来List<Node> rootNodes = new ArrayList<>();for (Node n : nodes) {if (n.getParent() == null) {rootNodes.add(n);}}//按照父子关系将节点一个个放进去,以达到排序目的List<Node> sortedNodes = new ArrayList<>();addNode(sortedNodes, rootNodes);return sortedNodes;}/*** 排序节点的具体实现方法* @param sortedNodes* @param rootNodes*/private static void addNode(List<Node> sortedNodes, List<Node> rootNodes) {for (Node n : rootNodes) {sortedNodes.add(n);if (n.children.size() > 0) {addNode(sortedNodes,n.children);}}}/*** 将一个节点的所有子节点的展开状态都设置为关闭* @param n*/public static void shutNode(Node n){List<Node> children = n.getChildren();if(children.size()>0){for (Node n1 : children) {n1.setExpand(false);shutNode(n1);}}}/*** 计算此节点左边距的空格个数* @param node* @param i* @return*/public static int calPadding(Node node,int i){if(node.parent!=null){i++;i=calPadding(node.parent,i);}return i;}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。