11

Suggestions for building a treeview control in Android

nas
  • 937
  • 1
  • 8
  • 21

4 Answers4

12

I built a treeview of my own which supports n levels. It's easy to use in touch screens, especially on devices with larger screen. I Used a class which extends ListviewAdapter and created my own listitem. the items know on which level they are and they inherit the expandstate of their parents (by remembering their own state). This Tree is quite fast up to thousand items. enter image description here

Edit: added the code, but the way I wrote in the comment, It won't be very helpful, because it's very close to my own needs.

package de.supinfo.FISDroid;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.PaintDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Bitmap mIcon1;

private int active_view;
private int last_path;
public String[][] values = new String[0][];

public EfficientAdapter(Context context, String[][] str_arr_values, int int_active_view) {
    // Cache the LayoutInflate to avoid asking for a new one each time.
    mInflater = LayoutInflater.from(context);
    values = str_arr_values;
    active_view = int_active_view;
}

public Object getItem(int position) {
    return position;
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {

    int padding = 0;

    // int selfstate = Integer.parseInt(values[position][4].trim());

    ViewHolder holder;
    if (convertView == null) {

        convertView = mInflater.inflate(R.xml.list_item_icon_text, null);

        holder = new ViewHolder();
        holder.text = (TextView) convertView.findViewById(R.id.text_view);
        holder.icon = (ImageView) convertView.findViewById(R.id.img_view);
        holder.expanded = (ImageView) convertView.findViewById(R.id.ImageView01);
        holder.llout = (LinearLayout) convertView.findViewById(R.id.list_item_icon_text);
        holder.docs = (TextView) convertView.findViewById(R.id.doc_count);
        holder.prun = (ImageView) convertView.findViewById(R.id.prun);
        holder.coord = (ImageView) convertView.findViewById(R.id.coord);
        holder.button = (Button) convertView.findViewById(R.id.button);
        holder.button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                main.tabHost.setCurrentTab(2);
            }

        });
        convertView.setTag(holder);
    } else {

        holder = (ViewHolder) convertView.getTag();
    }

    // Bind the data efficiently with the holder.
    String text = values[position][0];

    String docs = values[position][11];
    if (!docs.equals("0")) {
        // TODO
        // Anzeige das Dokumente vorhanden sind, eventuell Anzahl
        holder.docs.setText(docs);
        holder.docs.setVisibility(View.VISIBLE);
    } else {
        holder.docs.setVisibility(View.INVISIBLE);
    }
    holder.coord.setVisibility(values[position][12].equals("") || values[position][12].equals("0") || values[position][12].equals("0.0") ? View.INVISIBLE : View.VISIBLE);
    holder.prun.setVisibility(values[position][14].equals("") ? View.INVISIBLE : View.VISIBLE);
    holder.text.setText(text);
    holder.text.setTextSize(GlobalVars.Style.TextSize);
    if (position == active_view) {
        holder.text.setTextColor(R.color.headline_font);
        PaintDrawable pd = new PaintDrawable(Color.RED);
        holder.llout.setBackgroundDrawable(pd);
        holder.text.setSingleLine(false);
        holder.button.setVisibility(values[position][1].equals("-1") ? View.GONE : View.VISIBLE);
    } else {
        holder.text.setTextColor(R.color.headline_font);

        PaintDrawable pd = new PaintDrawable(Color.TRANSPARENT);
        holder.llout.setBackgroundDrawable(pd);
        holder.text.setSingleLine(true);
        holder.button.setVisibility(View.GONE);
    }

    int i = Integer.parseInt(values[position][5].trim());
    mIcon1 = GlobalHelper.GetIcon(i);
    holder.icon.setImageBitmap(mIcon1);

    if (values[position][8].equals("-1")) {
        holder.expanded.setVisibility(View.VISIBLE);
        holder.expanded.setImageResource(android.R.drawable.ic_input_add);
    } else if (values[position][8].equals("0")) {
        holder.expanded.setVisibility(View.INVISIBLE);
    } else if (values[position][8].equals("1")) {
        holder.expanded.setVisibility(View.VISIBLE);
        if (values[position][9].equals("1")) {
            holder.expanded.setImageResource(android.R.drawable.ic_menu_revert);
        } else {
            holder.expanded.setImageResource(android.R.drawable.ic_input_add);
        }
    }
    padding = Integer.parseInt(values[position][7].trim()) * 24;
    convertView.setPadding(padding, 5, 5, 5);

    return convertView;
}

static class ViewHolder {
    LinearLayout llout;
    TextView text;
    ImageView icon;
    ImageView expanded;
    ImageView coord;
    ImageView prun;
    TextView docs;
    Button button;
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return values.length;
}

public String[] getValues(int position) {
    return values[position];
}

public String getValue(int position) {
    return values[position][0];
}

public String getDatid(int position) {
    return values[position][1];
}

public String getPath(int position) {
    return values[position][2];
}

public String getParent(int position) {
    return values[position][3];
}

public void set_active_view() {
    active_view = GlobalVars.cn.index;
}

public int get_active_view() {
    return active_view;
}

public void set_last_path(int position) {
    last_path = position;
}

public int get_last_path() {
    return last_path;
}

}

Edit: added the xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/list_item_icon_text" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_height="wrap_content" 
android:layout_centerVertical="true" 
android:background="@color/tree_normal_back" 
android:padding="1dip" 
android:orientation="horizontal" 
android:layout_width="fill_parent">
<LinearLayout 
    android:id="@+id/plusminus" 
    android:layout_height="48dip" 
    android:layout_width="24dip" 
    android:gravity="right|center_vertical">
    <ImageView 
        android:id="@+id/ImageView01" 
        android:layout_height="24dip" 
        android:layout_width="24dip"/>
</LinearLayout>
<LinearLayout 
    android:id="@+id/LinearLayout01" 
    android:layout_height="48dip" 
    android:layout_width="48dip" 
    android:orientation="horizontal" 

    android:paddingLeft="4dip">
    <LinearLayout 
        android:id="@+id/LinearLayout02" 
        android:layout_height="48dip" android:orientation="vertical" android:layout_width="16dip">

        <TextView 
            android:text="0" 
            android:id="@+id/doc_count" 
            android:textColorHighlight="@color/headline_font" 
            android:layout_gravity="center_vertical" 
            android:textColor="@color/black" 
            android:textSize="12dip" 
            android:layout_margin="0dip" 
            android:padding="0dip" 
            android:paddingTop="0dip" 
            android:gravity="center_vertical|center_horizontal" 
            android:background="@drawable/ico_24_paperclip" 
            android:textStyle="normal" android:layout_height="16dip" android:layout_width="16dip">
        </TextView>
        <ImageView 
            android:id="@+id/prun" 
            android:layout_gravity="center_vertical" 
            android:layout_height="16dip" 
            android:layout_width="16dip" android:background="@drawable/ico_24_prun"/>
        <ImageView 
            android:id="@+id/coord" 
            android:layout_gravity="center_vertical" 
            android:layout_height="16dip" 
            android:layout_width="16dip"       android:background="@drawable/ico_24_coord"/>

    </LinearLayout>
    <ImageView 
            android:id="@+id/img_view" 
            android:layout_gravity="center_vertical" 
            android:layout_height="24dip" 
            android:layout_width="24dip" />

</LinearLayout>
<Button 
    android:id="@+id/button" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="@drawable/tabs_edit"
    android:focusable="false"
    android:visibility="gone">
</Button>
<TextView 
    android:layout_gravity="center_vertical" 
    android:padding="2dip" 
    android:marqueeRepeatLimit="2" 
    android:layout_width="wrap_content" 
    android:textSize="22dip" 
    android:textColor="@color/tree_normal_font" 
    android:id="@+id/text_view" 
    android:layout_height="wrap_content">
</TextView>  
</LinearLayout>
M D P
  • 4,209
  • 2
  • 18
  • 34
2red13
  • 10,616
  • 7
  • 37
  • 52
  • 3
    Nice! Would you care to share it? – Jeff Axelrod Apr 05 '11 at 00:00
  • 8
    -1 for boasting. It looks great but it's completely useless as an Answer, since you leave us completely on our own as to how to implement such a thing. All you're doing is showing off the fact that you found an answer, and you may as well have said "I can answer this" and left it at that. – Brian Lacy Dec 22 '11 at 17:09
  • sorry, but the code is very close to my needs, i wrote the basic thoughts how to solve the problem, the colde of the Adapter won't be very helpful... – 2red13 Dec 23 '11 at 09:35
  • 1
    Thanks for the edits, I've switched my -1 to a +. The code may be specific to your unique situation, but this way at least you've presented us with the foundation of a workable solution. :) – Brian Lacy Dec 23 '11 at 17:10
  • What does your "list_item_icon_text.xml" file look like? – phreed Mar 15 '12 at 22:13
  • Hello @2red13, the XML file has missing elements, could you please fix it ? – Leeeeeeelo Apr 23 '13 at 07:12
  • 4
    good answer but needed the full code if u have time send the link. – srinivas Apr 25 '13 at 10:23
  • Can you provide us a full project? It would be helpful for so many people. thanks in anticipation. – Faisal Shaikh May 17 '16 at 09:59
  • you cannot answer with your ego turned on. You can have your ego turned off first before answering. – Neon Warge Aug 30 '16 at 04:35
  • You shoud not comment with your brain turnend off. As i wrote at Dec 23 '11 at 9:35 , the code is very close to my needs, it would cost me a lot of time to make the stuff generic. with the provided informations you shoud be able to do it by yourself. – 2red13 Aug 30 '16 at 09:29
6

Here is a solution that our company open-sourced as a library (so very easy to re-use):

http://code.google.com/p/tree-view-list-android/

enter image description here

Jarek Potiuk
  • 12,572
  • 2
  • 50
  • 49
  • 1
    isn't is possible to do such tree without external libraries but with native android tools? – Sergey Oct 09 '11 at 08:01
5

The ExpandableListView is probably the closest existing thing. Keep in mind though that it might be hard for a user to fat finger a tree view.

Robby Pond
  • 70,876
  • 16
  • 121
  • 117
1

You can use this library: https://github.com/bmelnychuk/AndroidTreeView to get your required tree-view. It's a N-level tree where you can control every single node in tree.

Usage

1) install: compile 'com.github.bmelnychuk:atv:1.2.+'

2) build tree-view:

 TreeNode root = TreeNode.root(); 
 TreeNode parent = new TreeNode("node-name");
 TreeNode child0 = new TreeNode("child-node-name-1");
 TreeNode child1 = new TreeNode("child_node-name-2");

 parent.addChildren(child0, child1);
 root.addChild(parent);
Khairul Alam Licon
  • 410
  • 10
  • 19