android树状结构导航图
生活随笔
收集整理的這篇文章主要介紹了
android树状结构导航图
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文參考Hongyang大神文章 http://blog.csdn.net/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;} }總結
以上是生活随笔為你收集整理的android树状结构导航图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux yum安装mysql8
- 下一篇: 运用杨鹏17天搞定GRE单词的方法,算出