Android Multilevel tree-type list control _android

Source: Internet
Author: User
Tags stringbuffer

When we develop the app, we often encounter the need for multilevel list display. The Android Native SDK does not have a level 3 level 4 or more list control at all.
So we're going to implement a treelistview-like control, and here's an effect chart from my project that supports multilevel list extensions.

There are Expandlistview controls in Android, but this control supports only level two lists. For multilevel lists It's not easy to rewrite this.
The idea of implementing such a list is recursion, which constructs a relationship between child and parent.
I don't talk much about the code.
Activity

Package Com.example.customtreeviewdemo; 
Import java.util.ArrayList; 
 
Import java.util.List; 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import Android.view.View; 
Import Android.view.View.OnClickListener; 
Import Android.widget.Button; 
Import Android.widget.ListView; 
 
Import Android.widget.Toast; 
Import Com.example.customtreeviewdemo.bean.MyNodeBean; 
Import Com.example.customtreeviewdemo.tree.Node; 
 
Import Com.example.customtreeviewdemo.tree.TreeListViewAdapter.OnTreeNodeClickListener; 
  public class Mainactivity extends activity {private ListView Treelv; 
  Private Button checkswitchbtn; 
  Private mytreelistviewadapter<mynodebean> adapter; 
  Private list<mynodebean> Mdatas = new arraylist<mynodebean> (); 
 
  Whether the tag shows the checkbox or hides private Boolean ishide = true; 
    @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
 
    Setcontentview (R.layout.activity_main); Initdatas ();
    Treelv = (ListView) This.findviewbyid (R.ID.TREE_LV); 
     
    CHECKSWITCHBTN = (Button) This.findviewbyid (R.ID.CHECK_SWITCH_BTN); 
        Checkswitchbtn.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) { 
        if (ishide) {ishide = false; 
        }else{ishide = true; 
      } adapter.updateview (Ishide); 
    } 
       
    }); 
 
      try {adapter = new Mytreelistviewadapter<mynodebean> (Treelv, this, Mdatas, ishide); Adapter.setontreenodeclicklistener (New Ontreenodeclicklistener () {@Override public void OnClick (Node n 
                Ode, int position) {if (Node.isleaf ()) {Toast.maketext (Getapplicationcontext (), Node.getname (), 
          Toast.length_short). Show (); @Override public void Oncheckchange (node node, int position, LIST&LT;NODE&GT ; 
 
   Checkednodes) {       StringBuffer sb = new StringBuffer (); 
            for (Node n:checkednodes) {int pos = N.getid ()-1; 
 
          Sb.append (Mdatas.get (POS). GetName ()). Append ("---"). Append (pos + 1). Append (";"); 
        } toast.maketext (Getapplicationcontext (), sb.tostring (), Toast.length_short). Show (); 
    } 
 
      }); 
    catch (IllegalArgumentException e) {e.printstacktrace (); 
    catch (Illegalaccessexception e) {e.printstacktrace (); 
 
  } treelv.setadapter (adapter); 
    private void Initdatas () {Mdatas.add (new Mynodebean (1, 0, "Ancient China")); 
    Mdatas.add (New Mynodebean (2, 1, "Tang Dynasty")); 
    Mdatas.add (New Mynodebean (3, 1, "Song Dynasty")); 
    Mdatas.add (New Mynodebean (4, 1, "Ming Dynasty")); 
    Mdatas.add (New Mynodebean (5, 2, "Shimin")); 
 
    Mdatas.add (New Mynodebean (6, 2, "Li Bai")); 
    Mdatas.add (New Mynodebean (7, 3, "Kuangyin")); 
 
    Mdatas.add (New Mynodebean (8, 3, "Su Shi")); Mdatas.add (New MynodeBean (9, 4, "Zhu Yuanzhang")); 
    Mdatas.add (New Mynodebean (10, 4, "Tong Pak Fu")); 
    Mdatas.add (New Mynodebean (11, 4, "Wen Zhengming")); 
    Mdatas.add (New Mynodebean (12, 7, "Zhao established")); 
    Mdatas.add (New Mynodebean (13, 8, "Sudongdong")); 
  Mdatas.add (New Mynodebean (14, 10, "Chou Heung")); 

 } 
}

Adapter
This adapter is a treelistviewadapter that inherits its definition, and the core implementation is in Treelistviewadapter.

Package Com.example.customtreeviewdemo; 
 
Import java.util.List; 
Import Android.content.Context; 
Import Android.view.View; 
Import Android.view.ViewGroup; 
Import Android.widget.CheckBox; 
Import Android.widget.CompoundButton; 
Import Android.widget.CompoundButton.OnCheckedChangeListener; 
Import Android.widget.ImageView; 
Import Android.widget.ListView; 
 
Import Android.widget.TextView; 
Import Com.example.customtreeviewdemo.tree.Node; 
 
Import Com.example.customtreeviewdemo.tree.TreeListViewAdapter; public class Mytreelistviewadapter<t> extends treelistviewadapter<t> {public Mytreelistviewadapter (ListV Iew Mtree, context, list<t> datas, int defaultexpandlevel,boolean ishide) throws Illegalargume 
  Ntexception, illegalaccessexception {super (Mtree, Context, datas, defaultexpandlevel,ishide); @SuppressWarnings ("unchecked") @Override public view Getconvertview (node node, int position, view CONVERTVI EW, ViewGroup parent) {Viewholder viewholder = null; 
      if (Convertview = = null) {Convertview = Minflater.inflate (R.layout.list_item, parent, false); 
      Viewholder = new Viewholder (); 
      Viewholder.icon = (ImageView) convertview. Findviewbyid (R.id.id_treenode_icon); 
      Viewholder.label = (TextView) convertview. Findviewbyid (R.id.id_treenode_name); 
       
      Viewholder.checkbox = (CheckBox) Convertview.findviewbyid (R.id.id_treenode_check); 
 
    Convertview.settag (Viewholder); 
    else {Viewholder = (Viewholder) convertview.gettag (); 
    } if (Node.geticon () = = 1) {viewHolder.icon.setVisibility (view.invisible); 
      else {viewHolder.icon.setVisibility (view.visible); 
    ViewHolder.icon.setImageResource (Node.geticon ()); 
    } if (node.ishidechecked ()) {viewHolder.checkBox.setVisibility (view.gone); 
}else{viewHolder.checkBox.setVisibility (view.visible);      SETCHECKBOXBG (viewholder.checkbox,node.ischecked ()); 
     
     
    } viewHolder.label.setText (Node.getname ()); 
  return convertview; 
    Private Final class Viewholder {ImageView icon; 
    TextView label; 
  CheckBox checkbox; /** * CheckBox shows * @param CB * @param ischecked/private void setcheckboxbg (checkbox Cb,bo 
    Olean ischecked) {if (ischecked) {cb.setbackgroundresource (R.drawable.check_box_bg_check); 
    }else{Cb.setbackgroundresource (R.DRAWABLE.CHECK_BOX_BG); 

 } 
  } 
}

Custom Treelistviewadapter This is the entire tree structure of an adapter, which is mainly to implement node node operation Click, select Change Update, etc.

Package com.example.customtreeviewdemo.tree; 
Import java.util.ArrayList; 
 
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.CheckBox; 
Import Android.widget.CompoundButton; 
Import Android.widget.CompoundButton.OnCheckedChangeListener; 
Import Android.widget.ListView; 
 
Import Android.widget.RelativeLayout; /** * Tree Adapter * @param <T> * * Public abstract class Treelistviewadapter<t> extends Baseadapter {p 
  rotected context Mcontext; 
  /** * stores all visible Node */protected list<node> mnodes; 
  protected Layoutinflater Minflater; 
 
  /** * Stores all Node */protected list<node> mallnodes; 
 
  /** * Click on the callback interface * * Private Ontreenodeclicklistener Ontreenodeclicklistener; Public Interface Ontreenodeclicklistener {/** * processing node Click event * @param node * @param position 
    void OnClick (node node, int position); /** * Processing checkbox Select Change Event * @param node * @param position * @param checkednodes/void on 
  Checkchange (node node, int position,list<node> checkednodes); } public void Setontreenodeclicklistener (Ontreenodeclicklistener ontreenodeclicklistener) {This.ontreen 
  Odeclicklistener = Ontreenodeclicklistener; /** * * @param mtree * @param context * @param datas * @param defaultexpandlevel * Default exhibition A few trees * @throws illegalargumentexception * @throws illegalaccessexception/public Treelistviewadapter (List View Mtree, Context context, list<t> datas, int defaultexpandlevel, Boolean ishide) throws Illegalargu 
    Mentexception, illegalaccessexception {mcontext = context; 
     /** * Sort All node* * Mallnodes = treehelper. Getsortednodes (Datas, Defaultexpandlevel, ishide); 
    /** * filter out the visible node/mnodes = Treehelper.filtervisiblenode (mallnodes); 
 
    Minflater = Layoutinflater.from (context); 
      /** * Set the node to click, you can expand and shut down, and the ItemClick event will continue to be announced * * * 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), POS 
        ition); 
 
  } 
      } 
 
    });  /** * Corresponding ListView Click event to expand or close a node * * @param position/public void expandorcollapse (int position) 
 
    {Node n = mnodes.get (position); 
        if (n!= null)//excludes incoming parameter error exception {if (!n.isleaf ()) {N.setexpand (!n.isexpand ()); Mnodes = Treehelper.filterviSiblenode (Mallnodes); 
  Notifydatasetchanged ();//Refresh View}}} @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 (final int position, View Convertview, ViewGroup parent) {Final node node = m 
 
    Nodes.get (position); 
    Convertview = Getconvertview (node, position, Convertview, parent); 
    Set inner margin convertview.setpadding (node.getlevel () * 30, 3, 3, 3); 
      if (!node.ishidechecked ()) {//Get the parent layout of each node relativelayout MyView = (relativelayout) Convertview; 
      CheckBox checkbox under Parent Layout cb = (CheckBox) myview.getchildat (1); Cb.setoncheckedchangelistener (New Oncheckedchangelistener () {@Override public void oncheckedchanged (Co Mpoundbutton Buttonview, Boolean Ischecked) {treehelper.setnodechecked (node, ischecked); 
          list<node> checkednodes = new arraylist<node> (); 
            for (Node n:mallnodes) {if (n.ischecked ()) {Checkednodes.add (n); 
          } ontreenodeclicklistener.oncheckchange (Node,position,checkednodes); 
        TreeListViewAdapter.this.notifyDataSetChanged (); 
    } 
         
      }); 
  return convertview; 
 
  Public abstract View Getconvertview (node node, int position, View Convertview, viewgroup parent); /** * UPDATE * @param ishide/public void Updateview (Boolean ishide) {for (Node node:mallnodes) {n 
    Ode.sethidechecked (Ishide); 
  } this.notifydatasetchanged (); 

 } 
 
}

Node Model class

Package Com.example.customtreeviewdemo.bean; 
  public class Mynodebean {/** * Node ID */private int id; 
  /** * Node Parent ID * * private int pId; 
  /** * Node name */private String name; 
  /** * * */private String desc; 
   
   
  /** * Node Name length * * Private long length; 
    public Mynodebean (int id, int pId, String name) {super (); 
    This.id = ID; 
    This.pid = pId; 
  THIS.name = name; 
  public int getId () {return id; 
  The 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 String GetDesc () {return desc; 
  } public void Setdesc (String desc) {THIS.DESC = desc; 
  Public long GetLength () {return length; public void SetLength (long length) {this.length = length; 
 } 
   
   
}

Treehelper This is also the core action class, the main function is to match business data and node data

Package com.example.customtreeviewdemo.tree; 
Import Java.lang.reflect.Field; 
Import java.util.ArrayList; 
 
Import java.util.List; 
 
Import COM.EXAMPLE.CUSTOMTREEVIEWDEMO.R; public class Treehelper {/** * get visible node based on all nodes * * @param allnodes * @return * * public static Li St<node> Filtervisiblenode (list<node> allnodes) {list<node> visiblenodes = new ARRAYLIST&LT;NODE&G 
    t; (); for (node Node:allnodes) {//If the root node, or the upper directory is an expanded state if (Node.isroot () | | Node.isparentexpand ()) {SE 
        Tnodeicon (node); 
      Visiblenodes.add (node); 
  } return visiblenodes; /** * Get all the sorted nodes * * @param datas * @param defaultexpandlevel * @return * @throws Illegalarg Umentexception * @throws illegalaccessexception * * public static <T> list<node> Getsortednodes (List <T> datas, int defaultexpandlevel, Boolean ishide) throws Illegalaccessexception, Illegalargumentexception {list<node> sortednodes = new arraylist<node> (); 
    Convert user data to list<node> list<node> nodes = Convertdata2nodes (datas, ishide); 
    Get root node list<node> rootnodes = Getrootnodes (nodes); 
    Sort and set node relationships for (node Node:rootnodes) {AddNode (Sortednodes, node, defaultexpandlevel, 1); 
  return sortednodes; /** * Hangs all content on a node/private static void AddNode (list<node> nodes, node node, int DEFA 
    ultexpandleval, int currentlevel) {Nodes.Add (node); 
    if (defaultexpandleval >= currentlevel) {Node.setexpand (true); 
    } if (Node.isleaf ()) return; for (int i = 0; i < node.getchildrennodes (). Size (); i++) {AddNode (nodes, Node.getchildrennodes (). get (i), defaul 
    Texpandleval, CurrentLevel + 1); /** * Get all root nodes * * @param nodes * @return/public static LIST&LT;NODE&GT 
    Getrootnodes (list<node> nodes) {list<node> rootnodes = new arraylist<node> (); 
      for (node Node:nodes) {if (Node.isroot ()) {Rootnodes.add (node); 
  } return rootnodes; /** * Converts generic datas to node * * @param datas * @return * @throws illegalargumentexception * @thro WS Illegalaccessexception */public static <T> list<node> convertdata2nodes (list<t> datas, Boolea N ishide) throws Illegalaccessexception, illegalargumentexception {list<node> nodes = new arraylist< 
    Node> (); 
 
    node node = null; 
      for (T t:datas) {int id =-1; 
      int pId =-1; 
 
      String name = NULL; class<? 
      Extends object> clazz = T.getclass (); 
      field[] Declaredfields = Clazz.getdeclaredfields (); /** * corresponds to Mynodebean entity one by one */for (Field f:declaredfields) {if ("id". Equals (F.getname ())) {f.seTaccessible (TRUE); 
        id = f.getint (t); 
          } if ("PId". Equals (F.getname ()) {f.setaccessible (true); 
        PId = F.getint (t); 
          } if ("Name". Equals (F.getname ()) {f.setaccessible (true); 
        Name = (String) f.get (t); 
        } if ("desc". Equals (F.getname ())) {continue; 
        } if ("Length". Equals (F.getname ()) {continue; 
        } if (id = = 1 && pId = = 1 && name = null) {break; 
      node = new node (ID, pId, name); 
      Node.sethidechecked (Ishide); 
    Nodes.Add (node); /** * Compare all nodes in nodes, add children and Parent * for (int i = 0; i < nodes.size (); i++) {No 
      De n = nodes.get (i); 
        for (int j = i + 1; j < Nodes.size (); j + +) {Node m = Nodes.get (j); 
          if (n.getid () = = M.getpid ()) {n.getchildrennodes (). Add (m); M.SetParent (n); 
          else if (n.getpid () = = M.getid ()) {n.setparent (M); 
        M.getchildrennodes (). Add (n); 
    }}} for (Node n:nodes) {Setnodeicon (n); 
  return nodes; /** * Settings Open, close icon * * @param node/public static void Setnodeicon (node node) {if node.g 
    Etchildrennodes (). Size () > 0 && node.isexpand ()) {Node.seticon (R.drawable.tree_expand); else if (node.getchildrennodes (). Size () > 0 &&!node.isexpand ()) {Node.seticon (R.drawable.tree_econpa 
    nd); 
  Else Node.seticon (-1);  
    public static void Setnodechecked (Node node, Boolean ischecked) {//own set whether to select Node.setchecked (ischecked); 
    /** * Non-leaf node, sub-node processing * * setchildrennodechecked (node, ischecked); 
  /** parent Node Processing * * setparentnodechecked (node); /** * Non-leaf node, child node processing/private static void Setchildrennodechecked (Node node, Booleanischecked) {node.setchecked (ischecked); if (!node.isleaf ()) {for (node N:node.getchildrennodes ()) {//All child node settings are selected Setchildrennodechec 
      Ked (n, ischecked);  /** * Set Parent node selection * * @param node */private static void Setparentnodechecked (node node) 
      {/** Non-root node */if (!node.isroot ()) {node RootNode = node.getparent (); 
      Boolean isallchecked = true; 
          For (Node n:rootnode.getchildrennodes ()) {if (!n.ischecked ()) {isallchecked = false; 
        Break 
      } if (isallchecked) {rootnode.setchecked (true); 
      else {rootnode.setchecked (false); 
    } setparentnodechecked (RootNode); 

 } 
  } 
 
}

The core code is these, hope to be helpful to everybody.

Demo Source: Http://xiazai.jb51.net/201611/yuanma/AndroidTreeView (jb51.net). rar

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.