The previous article wrote about Expandablelistview, is the two-layer structure of the click, Android does not have three-layer structure of the components, this time need to expand their own, you can expand the Expandablelistview, you can also choose to expand the ListView. In order to achieve this effect, but also in search of a lot of articles (Chinese article you understand), there is a buddy in GitHub open source project, but package too much, look dizzy. See someone expand the ListView more in line with their own ideas, because the server side of the time is to load the top element, and then control the Click event Load the child below the parent, there is this understanding can go is to achieve a so-called N-level structure, start to the point:
Layout File
Create a new Activity_tree.xml layout file with a ListView on it:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http// Schemas.android.com/tools " android:layout_width=" match_parent " android:layout_height=" Match_parent " tools:context= "com.example.googletree.TreeActivity" > <listview android:id= "@+id/tree_list" android:layout_width= "match_parent" android:layout_height= "Match_parent"/></relativelayout>
Create a new Tree_item layout file:
<?xml version= "1.0" encoding= "Utf-8"? ><relativelayout xmlns:android= "http://schemas.android.com/apk/res/ Android " android:layout_width=" match_parent " android:layout_height=" match_parent "> < ImageView android:id= "@+id/homeimg" android:layout_width= "wrap_content" android:layout_height= " Wrap_content " android:layout_centervertical=" true " android:layout_alignparentleft=" true "/> < TextView android:id= "@+id/treetext" android:layout_width= "wrap_content" android:layout_height= " Wrap_content " android:layout_centervertical=" true " android:layout_torightof=" @id/homeimg "/> </RelativeLayout>
Demo Implementation
To display a tree-like data, first define a TreeNode class that holds the data:
public class TreeNode {/** literal content */private String contenttext;/** in the tree hierarchy */private int level;/** element ID */private int ID; /** the ID of the parent element */private int parendid;/** Whether there are child elements */private Boolean haschildren;/** Item expands */private boolean isexpanded;/** table Indicates that the node has no parent element, that is, a node of level 0 */public static final int no_parent = -1;/** means that the element is at the topmost layer */public static final int top_level = 0 ;p ublic TreeNode (String contenttext, int level, int id, int parendid,boolean haschildren, Boolean isexpanded) {super (); thi S.contenttext = Contenttext;this.level = Level;this.id = Id;this.parendid = Parendid;this.haschildren = HasChildren;this . isexpanded = isexpanded;} public Boolean isexpanded () {return isexpanded;} public void setexpanded (Boolean isexpanded) {this.isexpanded = isexpanded;} Public String Getcontenttext () {return contenttext;} public void Setcontenttext (String contenttext) {this.contenttext = ContentText;} public int Getlevel () {return level;} public void SetLevel (Int. level) {this.level = level;} public int GetId () {REturn ID;} public void setId (int id) {this.id = ID;} public int Getparendid () {return parendid;} public void Setparendid (int parendid) {this.parendid = Parendid;} public Boolean Ishaschildren () {return haschildren;} public void Sethaschildren (Boolean haschildren) {this.haschildren = HasChildren;}}
In order to populate the ListView in the view, you need to customize the Treeviewadapter:
public class Treeviewadapter extends Baseadapter {/** All data collection */private arraylist<treenode> allnodes;/** top-level elements combined */ Private arraylist<treenode> topnodes;/** layoutinflater */private layoutinflater inflater;/** The beginning of the item indent base */ private int indentionbase;public Treeviewadapter (arraylist<treenode> topnodes, arraylist<treenode> Allnodes, Layoutinflater inflater) {this.topnodes = Topnodes;this.allnodes = Allnodes;this.inflater = Inflater; Indentionbase = 20;} Public arraylist<treenode> Gettopnodes () {return topnodes;} Public arraylist<treenode> Getallnodes () {return allnodes;} @Overridepublic int GetCount () {return topnodes.size ();} @Overridepublic Object getItem (int position) {return topnodes.get (position);} @Overridepublic long Getitemid (int position) {return position;} @Overridepublic view GetView (int position, view Convertview, ViewGroup parent) {Viewholder holder = null;if (Convertview = = null) {holder = new Viewholder (); Convertview = Inflater.inflate (r.layout.treE_item, null); holder.homeimg = (ImageView) Convertview.findviewbyid (r.id.homeimg); holder.treetext = (TextView) Convertview.findviewbyid (R.id.treetext); Convertview.settag (holder);} else {holder = (Viewholder) Convertview.gettag ();} TreeNode element = Topnodes.get (position); int level =element.getlevel (); Holder.homeImg.setPadding (Indentionbase * ( Level + 1), Holder.homeImg.getPaddingTop (), Holder.homeImg.getPaddingRight (), Holder.homeImg.getPaddingBottom ()); Holder.treeText.setText (Element.getcontenttext ()); if (Element.ishaschildren () &&!element.isexpanded ()) { Holder.homeImg.setImageResource (R.drawable.open),///here to actively set the icon is visible, because Convertview may be reused "set up invisible" view, the same below. Holder.homeImg.setVisibility (view.visible);} else if (Element.ishaschildren () && element.isexpanded ()) {Holder.homeImg.setImageResource (R.drawable.open) ; holder.homeImg.setVisibility (view.visible);} else if (!element.ishaschildren ()) {Holder.homeImg.setImageResource (r.drawable.open); holder.homeImg.setVisibility (View.VISIBLE);} return Convertview;} Static class Viewholder{imageview homeimg; TextView Treetext;}}
call in activity:
public class Treeactivity extends Activity {/** The top-level element collection in the tree */private arraylist<treenode> topnodes;/** all element collections */priv Ate arraylist<treenode> allnodes; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (R.layout.activity_tree); Layoutinflater Inflater = (layoutinflater) getsystemservice (Context.layout_inflater_service); init (); ListView TreeView = (ListView) Findviewbyid (R.id.tree_list); Treeviewadapter treeviewadapter = new Treeviewadapter (Topnodes, Allnodes, Inflater); Treeviewitemclicklistener Treeviewitemclicklistener = new Treeviewitemclicklistener (treeViewAdapter); Treeview.setadapter (Treeviewadapter); Treeview.setonitemclicklistener (Treeviewitemclicklistener);} private void Init () {topnodes = new arraylist<treenode> (); allnodes = new arraylist<treenode> ();//Add node--node name , node level, node ID, parent node ID, whether there are child nodes, expand//Add outermost node TreeNode node1= new TreeNode ("Beijing", Treenode.top_level, 0, Treenode.no_ PARENT, True, false);//Add First layer nodeTreeNode node2= New TreeNode ("Haidian", Treenode.top_level + 1, 1, Node1.getid (), True, false);//Add second-level node TreeNode node3= new Tr Eenode ("West Two Flags", Treenode.top_level + 2, 2, Node2.getid (), True, false);//Add a third-tier node//treenode node7= new TreeNode ("Brilliant International", Tree Node.top_level + 3, 6, Node3.getid (), false, false);//Add first-level node TreeNode node4= new TreeNode ("Henan province", Treenode.top_level, 3, T Reenode.no_parent, True, false);//Add a second-tier node TreeNode node5= new TreeNode ("Zhengzhou", Treenode.top_level + 1, 4, Node4.getid (), TR UE, FALSE);//Add a third-tier node TreeNode node6= new TreeNode ("Jinshui", Treenode.top_level + 2, 5, Node5.getid (), false, false);//Add initial tree element Topnodes.add (Node1); Topnodes.add (NODE4);//Create Data source Allnodes.add (Node1); Allnodes.add (Node2); Allnodes.add (NODE3); Allnodes.add (NODE4); Allnodes.add (NODE5); Allnodes.add (node6);//allnodes.add (NODE7);} @Overridepublic boolean Oncreateoptionsmenu (Menu menu) {getmenuinflater (). Inflate (R.menu.tree, menu); return true;}}
public class Treeviewitemclicklistener implements Onitemclicklistener {/**-defined adapter */private treeviewadapter Treeviewadapter;public Treeviewitemclicklistener (Treeviewadapter treeviewadapter) {this.treeViewAdapter = Treeviewadapter;} @Overridepublic void Onitemclick (adapterview<?> parent, view view, int Position,long ID) {//Click on the item that represents the element TreeNode TreeNode = (TreeNode) treeviewadapter.getitem (position);//The element in the top layer of the tree arraylist<treenode> topnodes = Treeviewadapter.gettopnodes ();//The data source of the element arraylist<treenode> Allnodes = Treeviewadapter.getallnodes ();// Click on the item without the subkey to return directly if (!treenode.ishaschildren ()) {return;} if (treenode.isexpanded ()) {treenode.setexpanded (false);//delete node internal corresponding child node data, including child nodes of child nodes ... arraylist<treenode> Elementstodel = new arraylist<treenode> (); for (int i = position + 1; i < topnodes.size ( ); i++) {if (Treenode.getlevel () >= topnodes.get (i). Getlevel ()) Break;elementstodel.add (Topnodes.get (i));} Topnodes.removeall (Elementstodel); Treeviewadapter.notifydatasetchanged ();} else {treenode.setexpanded (true);//extract child node data from the data source into the tree, note that this is just adding the next level of child nodes, in order to simplify the logic int i = 1;//Note here The counter is placed on the for outside to ensure that the count is valid for ( TreeNode e:allnodes) {if (e.getparendid () = = Treenode.getid ()) {e.setexpanded (false); Topnodes.add (position + I, e); i + +; }}treeviewadapter.notifydatasetchanged ();}}}
The code is done, look at the initial effect:
Expand All:
This time the Node7 annotation in the treeactivity is canceled, that is, the effect of adding a third layer of nodes:
TreeNode node7= New TreeNode ("Brilliant International", Treenode.top_level + 3, 6, Node3.getid (), false, false);
The effect is as follows:
OK, infinite pole structure realized, Thursday happy ~ Beijing Good Morning ~
Android Infinite Polar Tree structure demo